Market prices in a script
Read Forever market values from JavaScript or Python.
Prerequisites#
- Node 18 or newer, for the built-in
fetch, or Python 3 with only its standard library. Nothing to install in either case. - No account and no key. The endpoint is
GET /api/market/prices.
Steps#
Know the two answers
Without a
realm, the endpoint lists the realms that have public prices. With one, it returns the items with the most units listed on that realm.GET /api/market/prices{ "ok": true, "dataAsOf": "2026-10-20T06:20:28.878Z", "realms": [], "attribution": { "licence": "CC BY-SA 4.0", "credit": "Data from Everloot (https://everloot.app), CC BY-SA 4.0.", "…": "…" } }{ "ok": true, "dataAsOf": "…", "rule": "A day is public when 3 reporters scanned this item on this realm with a full scan …", "fields": ["itemId", "market", "min", "historical", "quantity", "day", "reporters"], "realm": "<realm>", "items": [ [2589, 12345, 11000, 12000, 800, "2026-11-04", 4] ], "attribution": { "…": "…" } }Items are lists, not objects.
fieldsgives the order, so read it rather than counting positions. Prices are copper per unit: 10,000 copper is 1 gold, 100 copper is 1 silver.Save the script
Save one of these as
prices.mjsorprices.py. It lists the realms when you give it none, and prints up to ten items when you give it a realm. It handles an empty list, and stops with the wait time on a 429.prices// Forever market values for one realm. Run: node prices.mjs "Realm name" const die = (message) => { console.error(message); process.exit(1); }; const BASE = "https://everloot.app"; const realm = process.argv[2]; async function get(path) { const res = await fetch(`${BASE}${path}`); const body = await res.json(); if (res.status === 429) die(`Rate limited. Try again in ${res.headers.get("retry-after")} seconds.`); if (!res.ok) die(`${res.status}: ${body.error ?? "request failed"}`); return body; } if (!realm) { // Without a realm the endpoint lists the realms that have public prices. const { realms } = await get("/api/market/prices"); if (realms.length === 0) { console.log("No realm has public prices yet. A day is public once three players have scanned the realm."); } else { console.log("Realms with public prices:"); for (const name of realms) console.log(` ${name}`); console.log('Run again with a realm, for example: node prices.mjs "<realm>"'); } process.exit(0); } const data = await get(`/api/market/prices?realm=${encodeURIComponent(realm)}`); if (data.items.length === 0) { console.log(`No public prices for ${realm} yet.`); process.exit(0); } // Each item is a tuple in the order given by data.fields. const rows = data.items.map((tuple) => Object.fromEntries(data.fields.map((name, i) => [name, tuple[i]]))); const gold = (copper) => `${Math.floor(copper / 10000)}g ${Math.floor((copper % 10000) / 100)}s ${copper % 100}c`; for (const row of rows.slice(0, 10)) { console.log(`item ${row.itemId}: market ${gold(row.market)}, lowest ${gold(row.min)}, ${row.quantity} listed (${row.day})`); } console.log(data.attribution.credit);
"""Forever market values for one realm. Run: python prices.py "Realm name" """ import json import os import sys from urllib.error import HTTPError from urllib.parse import quote from urllib.request import urlopen BASE = "https://everloot.app" def get(path): try: with urlopen(BASE + path, timeout=30) as res: return json.load(res) except HTTPError as err: if err.code == 429: raise SystemExit(f"Rate limited. Try again in {err.headers['Retry-After']} seconds.") body = json.load(err) raise SystemExit(f"{err.code}: {body.get('error', 'request failed')}") def gold(copper): return f"{copper // 10000}g {copper % 10000 // 100}s {copper % 100}c" realm = sys.argv[1] if len(sys.argv) > 1 else None if realm is None: # Without a realm the endpoint lists the realms that have public prices. realms = get("/api/market/prices")["realms"] if not realms: print("No realm has public prices yet. A day is public once three players have scanned the realm.") else: print("Realms with public prices:") for name in realms: print(" " + name) print('Run again with a realm, for example: python prices.py "<realm>"') raise SystemExit(0) data = get("/api/market/prices?realm=" + quote(realm)) if not data["items"]: print(f"No public prices for {realm} yet.") raise SystemExit(0) # Each item is a list in the order given by data["fields"]. for tuple_ in data["items"][:10]: row = dict(zip(data["fields"], tuple_)) print(f"item {row['itemId']}: market {gold(row['market'])}, lowest {gold(row['min'])}, {row['quantity']} listed ({row['day']})") print(data["attribution"]["credit"])
Run it
Run it with no realm first.
Runnode prices.mjs
python prices.py
Today both print this, which is what an empty answer looks like:
OutputNo realm has public prices yet. A day is public once three players have scanned the realm.
Ask for a realm
Once a realm has public prices, the first run lists it, and you pass its name as the argument. Placeholder values:
First run, then a realmRealms with public prices: <realm> Run again with a realm, for example: node prices.mjs "<realm>"
item 2589: market 1g 23s 45c, lowest 1g 10s 0c, 800 listed (2026-11-04) item 2592: market 0g 2s 50c, lowest 0g 2s 0c, 90 listed (2026-11-04) Data from Everloot (https://everloot.app), CC BY-SA 4.0.
A realm with no public prices, or one that does not exist, gives an empty
itemslist, and the script says so.
Check your work#
- With no realm, the script prints either the empty-answer line or a list of realm names. A stack trace means the request failed; read its first line.
- With a realm, every line has an item id and three numbers. The copper amounts are whole numbers; if you see decimals, you are not reading this endpoint.
- The last line is the credit line. Show it wherever you publish these values.
- This endpoint allows 200 requests an hour for each IP address. Over that, the answer is a 429 with a
Retry-Afterheader in seconds, and the script prints it:Rate limited. Try again in 3132 seconds.
An empty list means no public values yet. It does not mean the price is zero.
Next steps#
- /market/prices: every field and the rule for when a day is public.
- market_value: one item's value and history, over MCP or plain HTTP.
- Licence and credit: the credit line to show.