Free, read-only EVE Echoes market, contract, planet and star chart data from StarStock. No key, no sign-up.
Base URL: https://api.starstock.app/api/v1
=IMPORTDATA("https://api.starstock.app/api/v1/items.csv")curl "https://api.starstock.app/api/v1/items/41000000000"
sell = the cheapest sell order (what you pay to buy now).
buy = the highest buy order (what you get selling now).
Jita prices are fields named cheapest_*; the best price in
all regions is everywhere_*. Items are identified by
type_id (Tritanium is 41000000000; find others with
search).
Load the market into an empty tab named Market (cell A1):
=IMPORTDATA("https://api.starstock.app/api/v1/items.csv")
Then look up a price by name from any other tab (A2 = item name). Column D is sell, E is buy, F is units for sale:
=INDEX(Market!D:D, MATCH(A2, Market!B:B, 0))
One item without a lookup tab (row 2, column 2 = sell; use column 3 for buy, 4 for units for sale):
=INDEX(IMPORTDATA("https://api.starstock.app/api/v1/items/41000000000.csv"), 2, 2)
Google refreshes IMPORTDATA on its own schedule (about hourly). Use one
whole-market tab rather than many single-item formulas.
https://api.starstock.app/api/v1/items.csv
=INDEX(items[cheapest_sell], MATCH(A2, items[name], 0))
(use the table name shown under Table Design).Add ?scope=all to any CSV link for all-regions prices instead of Jita
(the price columns are then named best_sell and best_buy).
Items with current prices, A to Z.
| Parameter | Meaning |
|---|---|
| limit, offset | Paging. limit 1 to 500 (default 100). |
| path | Only items in one category (a path from /categories). |
| ids | Up to 200 comma-separated type_ids, returned in that order. |
| live=1 | With ids: read the latest data instead of the list, which can be up to ~20 min behind. |
GET /items?ids=41000000000,51000000006&live=1
One item: current prices plus time-weighted averages over a window, and its estimate (see fields).
| Parameter | Meaning |
|---|---|
| window | 7d, 30d (default), 90d, 1y or all. |
| full=1 | Also include history for the window and a contracts summary:
how many open contracts offer or want the item, and the cheapest one selling only this item
(best.unit = ISK per unit incl. the 8% fee, best.id = contract_id), and
typical: the item's sell_p10_30d / p50 / p90 /
sell_src_30d plus sell_low_7d / everywhere_sell_low_7d (see fields). |
{ "ok": true, "item": { "type_id": 51000000006, "name": "Rich Veldspar",
"cheapest_sell": 28, "cheapest_buy": 25, "everywhere_sell": 26, "everywhere_buy": 25,
"average_sell": 29.43, "average_buy": 25.4, "vol_jita": 4645133, "activity": "active", ... },
"estimate": { "price": 26, "source": "market" } }
Price points for one item, oldest first. A point is recorded when the price or units for sale
changed. Takes window like above.
ts is Unix time in seconds. Points older than ~30 days are merged into one per
day (at 00:00 UTC) and may carry avg_* (that day's time-weighted average) and
close_* (the price at the end of the day)."carried": 1: the price already in effect when the window opened.Daily history files: every item's price points for one UTC day in one download. For the whole
market's history, use these instead of one /history request per item.
days = the dates with a file, newest first (about the last 4 weeks; a new day is added
after 01:00 UTC).
{ "ok": true, "days": ["2026-10-11", "2026-10-10", ...],
"fields": ["type_id", "ts", "cheapest_sell", ...], "url": "/api/v1/history/day/{date}" }
One day's file ({date} = YYYY-MM-DD). points is a list of
arrays in the order of fields: type_id, ts (Unix seconds),
cheapest_sell, cheapest_buy, everywhere_sell,
everywhere_buy, highest_sell, everywhere_highest_sell,
vol_jita, vol_all. Like /history, a point is recorded only when
something changed, so an item with no point that day kept its earlier price. A finished day never
changes, so a file only needs downloading once.
{ "ok": true, "day": "2026-10-11", "fields": [...],
"points": [[51000000006, 1791676800, 28, 25, 26, 25, 31, 31, 4645133, 9022871], ...] }
The order book: sell (cheapest first) and buy (highest first), each
{ price, qty, ss, rg, j } = price, quantity, solar system id, region id, and
j: 1 if the order counts as Jita. fetched_at = when the book was read.
The game shows at most ~220 sell orders per item, so very deep items (Tritanium, PLEX) are cut off at the expensive end. The buy side is complete. A book is re-read when the price moves, and at least every 24 hours.
Items by name, best match first. q needs at least 2 characters; limit
1 to 100 (default 30). total = how many items matched. categories = the
market categories the matches are in (path, count), biggest first; add
cat={path} to keep only that category.
Items whose price changed most recently. limit 1 to 150 (default 150).
The market's category tree, with the number of items in each category and its path.
Every item in one compact response (about 1.7 MB), with short keys:
| Key | Meaning | Key | Meaning |
|---|---|---|---|
| i | type_id | n | name |
| cs / cb | Jita sell / buy | es / eb | All-regions sell / buy |
| vj / va | Units for sale, Jita / all regions | ic | icon id |
| lj / la | Lowest sell in 7 days, Jita / all regions | q1 / q5 / q9 | 30-day typical sell price (see fields) |
| qs | Source of q1-q9: j Jita, a all regions |
The whole market, or one item, as CSV. Columns: type_id (whole market only),
name, path (whole market only), cheapest_sell,
cheapest_buy, volume (units for sale), last_updated,
estimated_price (the estimate price; empty = none).
?scope=all switches to all-regions prices; ?ids= (up to 200) limits
items.csv to those items.
Number of items tracked and when data last came in (last_updated).
Public contracts from across New Eden. New contracts appear within minutes;
accepted or cancelled ones are removed within about 30 minutes. Sellers are shown as an anonymous
code (seller), the same code for all of one seller's contracts. The accepter pays
price plus an 8% fee.
Every open public contract, newest first (about 600 KB). ?type_id= keeps contracts
that include that item; ?id= returns one contract.
{ "ok": true, "count": 591, "contracts": [ { "contract_id": 26259894, "type": 1,
"seller": "07fcc10f48f0", "price": 160000000, "date_expired": 1790757677,
"start_solar_system_id": 30004381, "items": [ { "t": 61999001320, "q": 1, "r": 0, "f": 0 } ], ... } ] }
Contracts completed (accepted) in the last 60 days, newest first. sold_at = when
StarStock saw it completed.
Contracts that ended without a sale in the last 60 days (ended:
expired or removed), newest first. Only contracts with up to 12 item
lines that include at least one item with no market price are kept.
Planets with resources and how much each one yields, from the game's own data. Resources are market items, so their prices come from the market endpoints.
Planets matching at least one filter. With resource, the planets with the most
output of it come first; otherwise they are in system order.
| Parameter | Meaning |
|---|---|
| resource | A resource's type_id or name, e.g. Lustering Alloy. |
| system | A solar system's id or name. |
| region, constellation | A region or constellation name. |
| limit, offset | Paging. limit 1 to 500 (default 100). total = how many planets matched. |
GET /planets?resource=Lustering%20Alloy®ion=The%20Forge&limit=1
{ "ok": true, "total": 409, "planets": [ { "name": "Fuskunen III", "planet_type": "Gas",
"system_id": 30000199, "system": "Fuskunen", "security": 0.2, "true_security": 0.23,
"constellation": "Mivora", "region": "The Forge", "jumps_from_jita": 15, "wormhole": false,
"output_bonus": 1.8, "resources": [ { "type_id": 42001000000, "name": "Lustering Alloy",
"richness": "Perfect", "output": 29.74 }, ... ] } ] }
The map and live layers behind the Star Chart, read from the game.
Systems are solar_system_ids. Kills, strongholds, Malpais, cyno and Sansha refresh about every 10 minutes;
the other layers about every 3 hours. Each layer has its own at time (UTC).
Every system on the star chart (about 1.4 MB), with regions, constellations, faction names and NPC station names.
x, y = position on the 2D chart; ly = 3D position in light-years.
gates = the systems its stargates lead to. faction_id 0 = none. off_chart_stations = stations in systems the chart doesn't draw.
{ "ok": true, "regions": [ { "id": 10000001, "name": "Derelik" }, ... ],
"constellations": [ { "id": 20000001, "name": "San Matar", "region_id": 10000001 }, ... ],
"factions": { "500001": "Caldari State", ... },
"systems": [ { "id": 30000001, "name": "Tanoo", "region_id": 10000001, "constellation_id": 20000001,
"true_security": 0.8583, "faction_id": 500007, "x": 0.01896, "y": -0.07305, "ly": [-9.3556, 4.4785, -4.7051],
"stations": [ "Tanoo IV - Trust Partners Trading Post", ... ], "gates": [ 30000003, ... ] }, ... ],
"off_chart_stations": [ { "name": "...", "system": "0IRK-R" }, ... ] }
Each region's outline on the 2D chart, as lists of [x, y] points in the same coordinates as
/starmap/systems (about 700 KB).
{ "ok": true, "regions": { "10000001": [ [ [0.1308, -0.0963], [0.1336, -0.0938], ... ] ], ... } }
The latest reading of every layer.
{ "ok": true, "received_at": "2026-10-10T21:57:26.992Z", "layers": {
"kills1h": { "at": "2026-10-10T21:57:26Z", "data": [ [30000195, 11], ... ] },
"sov": { "at": "2026-10-10T19:40:35Z", "data": { "30000208": [0, 1000022908, 2000000675], ... } }, ... } }
| Layer | data |
|---|---|
| kills1h | [[system, ships destroyed]] in the last hour. |
| kills24h | [[system, ships destroyed]] in the last 24 hours. |
| strongholds | [[system, level]]: pirate strongholds destroyed today as the game's level since 2026-10-15 (1 = 1-50, 2 = 51-100, 3 = 101-150, 4 = 151-200, 5 = over 200; before that, the count). The game resets it at 00:00 UTC. |
| strongholds_est | [[system, estimate]]: our estimate of today's count per system, from when each system reached each level (since 2026-10-15). |
| malpais | [[system, count]] from the game's [Malpais] High-activity systems filter. |
| cyno | [system] with cyno beacons. |
| sansha | { "incursions": [[constellation, race, end_at]], "boss_systems": [system] } |
| ansiblex | Ansiblex jump bridges: [[from, to, from_alliance, to_alliance, from_corp, to_corp]]. |
| keepstars | [system] with a Keepstar. |
| sov | Sovereignty: { system: [faction, corp, alliance] }. 0 = none. |
| colors | { owner id: "#rrggbb" }, the game's map colour for each sov owner. |
| alliances | { id: [ticker, name, logo, members] }. logo = the game's logo codes. |
| corps | { id: [ticker, name, logo, members] }. |
Days with a saved daily copy of the layers.
{ "ok": true, "dates": [ "2026-10-07", "2026-10-08", ... ] }
One day's copy (YYYY-MM-DD, UTC), same shape as /starmap/live plus date.
HTTP 404 for a day with no copy.
Pirate strongholds destroyed in each sov owner's systems (the Rat Board). The owner is the system's sov alliance, else its sov corp.
{ "ok": true, "today": "2026-10-10", "dates": [ "2026-10-09", "2026-10-10" ], "board": [ { "id": 2000000572,
"kind": "alliance", "ticker": "SOS", "name": "...", "logo": [41, 20, 21, 1, 19, 19, 1], "members": 2602,
"totals": { "today": 10645, "d3": 22323, "d7": 22323, "d30": 22323, "all": 22323 },
"corps": [ [ "THDG", "...", [10, 5, 7, 19, 32, 19, 56, 0], 95, 1000023717 ], ... ] }, ... ],
"corp_dates": [ "2026-10-11" ], "corp_board": [ { "id": 1000011193, "ticker": "THD", "name": "...",
"logo": [10, 5, 7, 19, 32, 19, 56, 0], "members": 331, "alliance": [ 2000000572, "SOS", "..." ],
"totals": { "today": 1229, "d3": 1229, "d7": 1229, "d30": 1229, "all": 1229 } }, ... ] }
totals: today so far, the last 3, 7 and 30 days (including today), and every day recorded
(dates). corps (alliances only): member corps holding its systems now, as
[ticker, name, logo, members, id].
corp_board: every corp holding sov systems (alliance members included), counting the systems
it holds, over the days in corp_dates (per-corp counts start 2026-10-11). alliance:
[id, ticker, name], or null for a corp without one.
top (every row): its 3 systems with the most strongholds destroyed per period,
{ "today": [[system, count], ...], "d3", "d7", "d30", "all" }, over the days in sys_dates
(per-system counts start 2026-10-11).
A route between two systems, worked out like the Star Chart's route finder. Systems and regions can be names (any case) or ids; lists are comma separated.
| Parameter | Meaning |
|---|---|
| from | Start system (required). |
| to | Destination system (required). |
| safest | 1 = stay in high-sec (0.5 and up) where a way exists. Default: fewest jumps. |
| sec_min | Lowest security to pass through, -1 to 1. The start and destination always count. |
| sec_max | Highest security to pass through, -1 to 1. |
| avoid_systems | Systems never to pass through (up to 100). |
| avoid_regions | Regions never to pass through (up to 100). |
| ansiblex | 1 = also use Ansiblex jump bridges (both directions) from the latest ansiblex layer. |
| cyno | 1 = also jump to cyno beacons from the latest cyno layer, from systems below 0.45 true security. Needs ship = a ship that can fit a jump drive. |
| cyno_range | Jump range in light-years (0.1 to 50) instead of the ship's base range. |
| ship | Any ship name: adds travel_time_s. |
/starmap/route?from=Jita&to=Amarr&safest=1&ship=Rifter
{ "ok": true, "from": { "id": 30000142, "name": "Jita", "region": "The Forge" },
"to": { "id": 30002187, "name": "Amarr", "region": "Domain" },
"jumps": 9, "low_sec": 0, "null_sec": 0, "ship": "Rifter", "travel_time_s": 304,
"steps": [ { "to": { "id": 30002187, "name": "Amarr" }, "via": "gate", "jumps": 9 } ],
"route": [ { "id": 30000142, "name": "Jita", "region": "The Forge", "security": 0.9, "via": null },
{ "id": 30000144, "name": "Perimeter", "region": "The Forge", "security": 1, "via": "gate" }, ... ],
"filters": { "safest": true, "sec_min": null, "sec_max": null, "avoid_systems": [], "avoid_regions": [],
"ansiblex": false, "cyno_range": null },
"star_chart_url": "https://starstock.app/starmap?route=30000142-30002187&safe=1" }
route: every system in order, with its security as the chart shows it (rounded to 0.1) and how it is
reached: via gate, ansiblex or cyno (null for the start).
steps: the autopilot steps, each run of stargate jumps as one step and each Ansiblex or cyno jump as its own.
low_sec / null_sec: systems passed through (not the start) at 0.1 to 0.4 / 0.0 and below.
travel_time_s: seconds, from the game's own formula with the ship's base stats (no skills), starting 30 AU
from the first gate like the game; null without a ship or when the route has an Ansiblex or cyno jump.
live (only with ansiblex or cyno): the at time of the layer used,
null when none is newer than 12 hours. star_chart_url opens the same route on the Star Chart.
The game's autopilot picks its own way between steps.
HTTP 400 for a missing or unknown system, ship or region, or a bad number; 404 when no
route exists (with the filters given). Both answer { "ok": false, "error": "..." }.
| Field | Meaning |
|---|---|
| cheapest_sell / cheapest_buy | Best Jita sell / buy price (ISK). null = no orders. |
| everywhere_sell / everywhere_buy | Best sell / buy price in any region. |
| highest_sell, everywhere_highest_sell | Most expensive listed sell order (item detail only). |
| vol_jita / vol_all | Units listed for sale, Jita / all regions. Supply, not units traded. |
| sell_order_count | Number of sell orders, all regions. |
| activity | active (6+ sell orders), low (2 to 5), minimal (1), no orders. |
| average_* | Time-weighted average over the window (item detail only). |
| sell_high_7d / sell_low_7d | Highest / lowest Jita sell price in the last 7 days (everywhere_sell_*_7d for all regions). |
| sell_p10_30d / p50 / p90 | 30-day typical sell price: the price was at or below this 10% / 50% / 90% of the time. sell_src_30d: j Jita, a all regions. |
| estimate | On /items/{type_id} (next to item) and on every /items row: the Estimated price shown on the item page,
as { "price", "source" }. source market = from market sell prices (the lower of the usual
30-day low and today's price). Items with no market price are estimated from contracts:
contracts_sold = middle price of completed contracts, contracts_asking = the cheapest asking price on
contracts (nobody has bought one yet), with count = how many contracts or sellers it's from. It switches back to
market as soon as the item has market prices. null = no estimate. |
| last_updated | When the price last changed (ISO 8601, UTC). |
| last_checked | When the item was last read. Can lag up to ~45 minutes for an item whose price didn't change. |
| path | Category, e.g. Manufacturing Materials > Minerals > minerals(10). |
| icon_url | Relative to https://starstock.app/. null = no icon. |
| Field | Meaning |
|---|---|
| type | 1 item exchange, 2 auction. |
| seller, seller_corp | Anonymous codes for the seller and their corporation. |
| price | ISK the accepter pays (before the 8% fee). top_bid: highest bid on an auction. |
| reward | ISK the accepter receives. |
| items | t type_id, q quantity, r: 1 = the seller wants this item in return, f: 1 = fitted inside another item in the contract. |
| date_issued, date_expired | Unix time in seconds. first_seen = when StarStock found it. |
| start_solar_system_id | Where the contract is. start_solar_system_name = its name (open contracts only). |
| description | The seller's note (up to 200 characters). |
| volume, collateral | Size in m³ and collateral (ISK). |
| Field | Meaning |
|---|---|
| name, planet_type | Planet name and type (Temperate, Barren, Oceanic, Ice, Gas, Lava, Storm or Plasma). |
| system_id, system, constellation, region | Where the planet is. |
| security, true_security | Security status as the game shows it, and the exact value. |
| jumps_from_jita | Stargate jumps from Jita. null = no stargate route from Jita (wormhole systems and a few far regions). |
| wormhole | true = in wormhole space. |
| output_bonus | How many times more this system's planets yield than the same planet at 1.0 security. Already included in output. |
| resources | type_id, name, richness (Perfect, Rich, Medium or Poor) and output = units per hour per extraction array. |
429 for 10 seconds. Spread requests out (about 1 per second keeps you well clear).429 with a Retry-After header (seconds) and reset_at (Unix time in milliseconds)./items, /categories, /catalog.json and the CSVs are built from a
list refreshed about every 20 minutes; single items, /search and /recent are live./catalog.json or /items.csv
request, and for history the daily files at /history/days, not one request per item./items/{type_id}, its /history
and /orders) per network per UTC day (IPv4 /24, IPv6 /64). Some cloud hosts share one count of 500 for all their addresses. Cached answers don't count. Over that you
get 429 with a Retry-After header until 00:00 UTC.503 with a Retry-After header until 00:00 UTC. API requests
(/api/v1) for single items, their history and CSV pause earlier, at 75% of the budget, so the
site keeps working; the bulk endpoints and order books keep working.{ "ok": false, "error": "..." } with a 4xx or 5xx status.
Unknown items and addresses return 404.Use of the API is covered by the terms. Questions or feedback: the StarStock Discord, linked from starstock.app.