← Hardcore Market Tools · Interactive docs
Hardcore World Tool Kit - data API
Read-only market data for the Hardcore Worlds. Whole-market Grand Exchange prices for the Hardcore Worlds, updated every few minutes.
Data from this service must not be used for real-world trading. It is a community tool for the game's Grand Exchange, provided as is.
The basics
- Open to everyone: no key, no account, no sign-up. Plain
GETrequests; the answers are JSON. - Any website may call it from a browser (CORS is open for reads). Nothing can be written through it: uploads need a key that only the plugin holds.
- Times are Unix seconds (UTC). Prices and totals are in gp.
- Trades and open offers come from players using the free plugin. Their prices are adjusted to line up with the market. Names, ids and accounts of the players are never in the data: a trade is only an item, a side, a price, a quantity and a time.
- Answers are shared and kept for up to a minute, so asking more often than that gets you the same data. A client that asks far too often may be refused (HTTP 429 or 503).
- Errors come as
{"error": "..."}with a status: 400 for a bad parameter, 404 for an unknown path or item, 429 or 503 when you or the server are too busy (503 carriesRetry-After). - Fields may be added over time. Ignore the ones you don't know.
curl https://HOST/v1/items?ids=2,4151
Replace HOST with this page's address.
GET /v1/items
Every item on the market: the prices of the last 24 hours and the current offers.
| Parameter | Meaning |
|---|---|
ids | Optional. Up to 100 comma-separated item ids (?ids=2,4151). Without it, every item. |
world | Optional. Not needed: this service always answers for the Hardcore Worlds, which share one economy (shown as world 9000), whatever you pass. |
include | Optional extras, comma-separated: fill (lastFillBuy, lastFillSell and their ...Time, the same as lastBuy and lastSell where a live trade was reported), trust (a reference price trustedPrice with trustedVotes and trustedPriceTime, trustedBestBid and trustedBestAsk, and vol24 split in the share of plugin-reported volume that two sides confirmed, all of it when plugin users reported none: confVol24 and unconfVol24). |
{ "time": 1793735269, "world": null, "pricesAsOf": 1793735100,
"items": [ { "id": 4151, "name": "Abyssal whip", "hasIcon": true,
"vol24": 12, "gp24": 3100000, "reporters24": 3, "avgBuy24": 258000, "avgSell24": 259000,
"lastBuy": 258000, "lastBuyTime": 1793734000, "lastSell": 259000, "lastSellTime": 1793733000,
"bids": 2, "asks": 4, "bestBid": 255000, "bestAsk": 262000, "bidQty": 3, "askQty": 9 } ] }
| Field | Meaning |
|---|---|
pricesAsOf | When the prices were last updated (Unix seconds, at the top of the answer). |
vol24, gp24 | Units and gp traded across the whole market in the last 24 hours. |
reporters24 | How many different players' plugins reported trades of this item in the last 24 hours. |
avgBuy24, avgSell24 | Volume-weighted average price of the buys and of the sells over the last 24 hours. Missing when there were none. |
lastBuy, lastSell (+ Time) | The latest price on each side and when it happened. Missing when never seen. |
estimated | Present and true for a rough price: the item trades too little for a firm figure. |
bids, asks, bestBid, bestAsk, bidQty, askQty | The open offers players have in the Grand Exchange (the number of offers, the highest buy and lowest sell price adjusted to line up with the market, the quantity wanted and for sale). Offers not refreshed for 14 days are ignored. |
trustedBestBid, trustedBestAsk | With include=trust: the actual listed offer price. |
GET /v1/item/{id}
One item: a summary, its latest trades and its order book.
| Parameter | Meaning |
|---|---|
limit | Optional. Trades to return, 1 to 500 (default 100). |
before | Optional. A cursor for older trades: pass the nextBefore of the previous answer. |
world, include | As above. |
{ "id": 4151, "name": "Abyssal whip", "hasIcon": true,
"summary": { "lastBuy": 258000, "lastBuyTime": 1793734000, "lastSell": 259000, "lastSellTime": 1793733000,
"vol24": 12, "avgBuy24": 258000, "avgSell24": 259000, "bestBid": 255000, "bestAsk": 262000 },
"trades": [ { "kind": "fill", "side": "buy", "qty": 1, "price": 258000, "total": 258000,
"ts": 1793734000, "late": false, "world": 9000 } ],
"book": { "bids": [ { "price": 255000, "offers": 1, "qty": 2, "oldest": 1793700000 } ],
"asks": [ { "price": 262000, "offers": 2, "qty": 5, "oldest": 1793690000 } ] },
"nextBefore": "1793733000_15123" }
trades[].kind:fillis a trade seen as it happened;historywas read later from the game's Grand Exchange History tab (solateis true and the time is approximate);cancelledis an offer that was cancelled.sideisbuyorsell.- Trade prices and totals and the prices in
bookare adjusted to line up with the market.late: time approximate, or price adjusted to the market. book: open offers grouped by price.oldestis when the oldest offer at that price was placed. Bids are listed highest first, asks lowest first.nextBeforeisnullwhen there are no older trades.
GET /v1/item/{id}/series
The price history of one item, as averages per time bucket (for a chart).
| Parameter | Meaning |
|---|---|
range | Optional: 24h, 7d, 30d, 90d or 1y. Each has a default step (5 minutes, 1 hour, 6 hours, 6 hours, 1 day). |
step | Optional bucket size: 5m, 1h, 6h or 24h. Without range, the last 365 buckets of that size (default 1h). With one, it is used unless it would give more than 2016 buckets. |
world, include | As above (include=trust adds confAvgBuy and confAvgSell, which on the market's own points repeat the point's prices, and confBuyVolume and confSellVolume, the point's volumes in the share of plugin-reported volume that two sides confirmed. Points from plugin trades, where the market's data does not reach, carry the confirmed plugin-trade figures at market prices, so those can differ from the point's prices or be null). |
{ "id": 4151, "step": "1h", "range": "7d",
"data": [ { "timestamp": 1793732400, "avgBuy": 258000, "avgSell": 259000, "buyVolume": 2, "sellVolume": 1 } ] }
timestamp is the start of the bucket. A bucket without trades on one side has null for that average. Buckets with no trades at all are left out.
GET /v1/recent
The live feed of events (trades and offers), newest first, with the totals of the last 24 hours.
| Parameter | Meaning |
|---|---|
limit | Optional. 1 to 200 events (default 50). |
kinds | Optional filter, comma-separated: placed, fill, cancelled, history. The stats are not filtered. |
after | Optional. An event id: only events newer than it. Keep the newest id you have seen and pass it next time to receive only what is new. |
before | Optional. An event id: only events older than it (for paging back). |
world | As above. |
{ "time": 1793735270,
"stats": { "events24": 666, "reporters24": 26, "units24": 196586, "gp24": 119488147,
"openBids": 41, "openAsks": 97, "tradersWithOffers": 39 },
"events": [ { "id": 15126, "kind": "placed", "side": "buy", "itemId": 22552, "name": "Thammaron's sceptre (u)",
"hasIcon": true, "qty": 1, "price": 10000000, "total": null,
"ts": 1793734311, "late": false, "receivedAt": 1793734320 } ] }
placed is an offer put into the Grand Exchange (its total is null: nothing traded yet); fill is a trade.
receivedAt is when the server got it, rounded down to the minute. reporters24 counts the plugins that reported anything in the last 24 hours. units24 and gp24 are the whole market. Event prices are adjusted to line up with the market.
GET /v1/icon/{id}
The item's icon as a PNG (answers 404 when there is none; hasIcon in the other answers says whether there is one). Cached by browsers for a day.
GET /v1/health
{"ok": true, "time": 1793735270}, or status 503 with "ok": false when the database can't be reached.
Privacy
This API publishes prices, quantities and times only. How the data is collected, which identifiers the server keeps and for how long is in the privacy notice.
Questions or problems: Discord @Novith.