StockX Scraper - Ask, Bid, Last Sale by Size avatar

StockX Scraper - Ask, Bid, Last Sale by Size

Pricing

from $1.40 / 1,000 market records

Go to Apify Store
StockX Scraper - Ask, Bid, Last Sale by Size

StockX Scraper - Ask, Bid, Last Sale by Size

Scrape StockX market data by keyword, category or URL. Every row carries lowest ask, highest bid, last sale, bid ask spread, ask counts, 72 hour and 90 day sales volume, 12 month average price, volatility and premium over retail. Pick a size and every row becomes that size's own order book.

Pricing

from $1.40 / 1,000 market records

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

5 days ago

Last modified

Categories

Share

StockX Scraper: Live Ask, Bid and Last Sale by Size

StockX Scraper turns StockX into a market data feed for sneakers, streetwear, apparel and collectibles. Search by keyword, browse a category, or paste StockX links, and get back the numbers a reseller actually trades on: lowest ask, highest bid, last sale, the bid/ask spread, ask depth by shipping speed, 72 hour, 90 day and 12 month sales volume, price volatility and the premium over retail. Pick a size and every row becomes that size's own order book, which is the grain a trade actually gets priced against. Export the dataset to JSON, CSV or Excel, or read it straight through the API.

Why This Scraper?

  • Two ways to start. Search by keyword or paste StockX product, search, category or brand links; most filters apply to both, except a pasted product URL, which always returns that one product in full. Most filters narrow the site's own pages read; four (minimum last sale, minimum recent sales, live-ask-only, live-bid-only) are checked after a page is read instead.
  • The live market is on every row, no surcharge. Lowest ask, highest bid, last sale, the bid/ask spread, ask depth by shipping speed and 72 hour, 90 day and 12 month sales volume come back whether or not full product details are switched on.
  • Size level order books. Set a size scale and a size and every row becomes that one size's own market. Turn on full product details instead and each row carries the whole size table, every size with its own order book and its own sale history.
  • Filter honesty. StockX echoes back the filter set it actually resolved on every result page. The run reports that echo and warns when a filter you asked for was not applied, so a page that quietly widened never reads as a narrower result than it is.
  • Multi market pricing. Seven StockX country markets, each with its own live order book and its own currency, not a currency conversion of one market.
  • Built for monitoring. Incremental mode tracks a saved search over time and returns only new and updated records by default; reappeared and expired ones need Emit expired too. Resume continues one interrupted run without paying twice for what it already collected.
  • A run that could read nothing fails instead of returning empty. "Nothing matched this search" and "the connection could not be read" are tracked separately, so a fully blocked run never comes back looking like an honestly empty one; a run that read at least something still succeeds even if part of it was refused.

Use Cases

  • Resale trading and arbitrage: compare lowest ask, highest bid and spread across sizes to find where a flip is actually worth doing.
  • Pricing and inventory tools: feed live ask, bid and last sale data into your own storefront or pricing engine.
  • Market research: build historical sales volume, volatility and price premium datasets across sneakers, apparel or collectibles.
  • Drop and price monitoring: track a search or category on a schedule and get only new items and items whose price or sales statistics changed, not a full re-download.
  • Demand modeling and data science: use per size sale history and 72 hour, 90 day and 12 month volume to model demand and seasonality.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
rowType"variant" (also "product" for a whole-product row)
recordId"a1b2c3d4-2222-4a2b-9c3d-000000000002"
productId / variantId"a1b2c3d4-1111-4a2b-9c3d-000000000001" / "a1b2c3d4-2222-4a2b-9c3d-000000000002"
title"Northaven Trailcore 02 Storm Grey Ember"
brand / model"Northaven" / "Northaven Trailcore 02"
url"https://stockx.com/northaven-trailcore-02-storm-grey-ember"
size / sizeType"9" / "us m"
requestedSize"US M 9"
sizeConversions[{ "size": "US M 9", "type": "us m" }, { "size": "UK 8", "type": "uk" }]
lowestAsk210
highestBid178
lastSale205
bidAskSpread32
standardAskCount / standardLowestAsk54 / 210
expressNextDayAskCount / expressNextDayLowestAsk9 / 228
salesLast72Hours21
salesLast90Days / averagePriceLast90Days640 / 198
salesLast12Months / averagePriceLast12Months2100 / 205
priceVolatility0.087
pricePremium0.45
market / currency"US" / "USD"
releaseDate"2022-11-05"
gender / productCategory"men" / "sneakers"
imageUrl"https://images.stockx.com/images/Northaven-Trailcore-02-Storm-Grey-Ember-Product.jpg"
scrapedAt"2026-09-20T09:15:00Z"

With Fetch full product details on, each row also carries styleId, colorway, retailPrice, restockDate, sizeConversionTypes, images, tags, traits, detailDescription, and the full availableSizes table: every size the product offers, each with its own lowestAsk, highestBid, lastSale, bidAskSpread, askCount and sales volume. breadcrumbs and productLine are only added when a product's own page had to be read directly rather than through the main listing path; per-size saleHistory and the saleHistoryPoints count are only added by that same main path, so no single row carries both sets together. In incremental mode, records also carry changeType (NEW, UPDATED, UNCHANGED by default; REAPPEARED/EXPIRED only with Emit expired too), changedFields, firstSeenAt and lastSeenAt.

How to Use

  1. Pick a mode: search (by keyword) or url (paste StockX links).
  2. Add filters to narrow the scope: category, brand, gender, colour, price range, availability, or set a size scale and a size to get one row per size instead of one row per product.
  3. Turn on Fetch full product details if you want the style code, colourway, retail price and the whole size table (adds a per record surcharge); it is pre-checked in the Console form, uncheck it for a fast, cheaper market crawl.
  4. Set Max items to control run size and cost, then click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.

The order book for one size, across a search:

{
"mode": "search",
"searchTerms": ["trail runner"],
"sizeScale": "mens",
"size": "10",
"orderBy": "most-active",
"maxItems": 100
}

Everything trading right now, under retail:

{
"mode": "search",
"category": "sneakers",
"belowRetailOnly": true,
"minSalesLast72Hours": 5,
"orderBy": "most-active",
"maxItems": 200
}

Paste links (search, brand and product):

{
"mode": "url",
"urls": [
"https://stockx.com/search?s=trail+runner",
"https://stockx.com/northaven",
"https://stockx.com/northaven-trailcore-02-storm-grey-ember"
],
"fetchDetails": true,
"maxItems": 50
}

Daily monitoring of one search:

{
"mode": "search",
"searchTerms": ["retro basketball high"],
"incrementalMode": true,
"stateKey": "retro-basketball-watch",
"maxItems": 0
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/stockx-market-data-scraper").call(
run_input={"mode": "search", "searchTerms": ["trail runner"], "maxItems": 50})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["title"], row["lowestAsk"], row["highestBid"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/stockx-market-data-scraper').call({
mode: 'search', searchTerms: ['trail runner'], maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Honesty about scope and filters

StockX returns at most 1000 results for any one search or category. When a scope hits that ceiling the run says so explicitly and suggests narrowing it with the brand, model, size, colour, price or availability filters; a truncated scope is never reported as a complete one. Sponsored placements on result pages are dropped before they reach the dataset, so they are never counted or billed as a row.

Resume and recurring updates

These are two different tools. Resume (resumeFromRunId) continues one specific interrupted run: paste its run or dataset id, and this run walks the same scope from its start page again, skipping every record id the earlier run already returned, so nothing already collected is re-emitted or re-billed. Because it re-walks every page rather than jumping to where the earlier run stopped, it also picks up any item that has shifted into an earlier page since that run, at the cost of reading (but not paying for) pages already read once; those re-read pages still count against Max pages, so set it generously on a resumed run.

Incremental mode (incrementalMode) is for running the same search again and again on a schedule. Each record is classified NEW, UPDATED (with changedFields), or UNCHANGED (suppressed and not billed unless emitUnchanged is on) by default. A price move on ask, bid or last sale always counts as UPDATED, since on a resale marketplace a moving price is the signal, not noise; so does a change in the sales-volume or average-price statistics; an ask simply re-listed at the same amount does not. REAPPEARED and EXPIRED additionally need emitExpired on: EXPIRED is only produced by a run with emitExpired on that scanned the tracked scope all the way to its natural end, with no cap, no Resume, no refusal and no page limit in the way, and REAPPEARED only for a record a previous such run marked EXPIRED. A partial run still saves what it saw (so NEW/UPDATED records and lastSeenAt are kept), it just never marks unseen records EXPIRED. stateKey names or deliberately shares one monitoring campaign; leave it empty and the actor derives one from the search terms, URLs and filters, so two different searches never share a baseline. Resume and incremental mode are not combined on the same state: turning on incremental mode against a state key that already has saved history while also setting Resume stops the run before anything is collected or charged, rather than risk double billing.

Send results into your apps (MCP connectors)

Optionally pipe results into Notion, Linear, Airtable or Apify via MCP connectors, in the Export to your apps (MCP connectors, optional) section of the input. Each connector receives a condensed summary per record; the complete record always stays in the dataset, so nothing is lost if you leave this off.

  • mcpConnectors: the MCP connectors to export this run's records into (Notion, Linear, Airtable, Apify). Leave it empty and nothing is exported.
  • notionParentPageUrl: Notion connector only, the page under which one child page per record is created. Required when mcpConnectors includes Notion, ignored otherwise.
  • maxNotifyListings: how many records are exported to each connector in one run. This caps the export only, it never changes what the dataset returns.

Export runs after the dataset is complete and is best effort: if a connector is unreachable the run still succeeds with a warning, and your records are still in the dataset.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch runs StockX keyword searches; url walks the StockX links you paste.
searchTermsarray["air jordan 1"]Search mode only: one or more keywords, each walked independently.
urlsarray(none, prefill shows a sample StockX link)URL mode only: StockX product, search, category or brand links.
categorystring(any)Restrict to a StockX category, top level or sneaker sub category. Applies in both modes.
brandsarray(none)One or more brand slugs, combined with OR. Applies in both modes.
modelsarray(none)One or more StockX model slugs, combined with OR. Applies in both modes.
productLinesarray(none)One or more product line slugs; StockX rebuilds this list per scope, so it is free text.
genderstring(any)Men, women, kids or unisex. Applies in both modes.
colorstring(any)One of the 10 colours StockX indexes. Applies in both modes.
activitystring(any)Running, basketball, skateboarding, soccer, hiking, golf or football.
shoeHeightstring(any)Low, mid or high cut. Applies in both modes.
marketstringUSWhich StockX country market and currency to price against; the market follows the connection's exit country.
sizeScalestring(off)Turns on per size rows when set together with Size: men's, women's or kids. Setting a size with no category picked automatically selects the sneakers category.
sizestring(none)The size to price, in the scale above. Ignored unless Size scale is set.
minPriceUsdinteger(none)Only items whose lowest ask is at least this many US dollars.
maxPriceUsdinteger(none)Only items whose lowest ask is at most this many US dollars.
availableNowbooleanfalseOnly items with a live ask right now.
xpressShipOnlybooleanfalseOnly items available with expedited, pre verified shipping.
belowRetailOnlybooleanfalseOnly items whose lowest ask is below original retail price.
minLastSaleUsdinteger(none)Drop rows whose most recent sale was below this; applied to the rows this run reads, since StockX has no server side filter for it.
minSalesLast72Hoursinteger(none)Drop rows with fewer than this many sales in the last 72 hours; applied to the rows this run reads.
hasLiveAskOnlybooleanfalseDrop rows with no live ask; applied to the rows this run reads.
hasLiveBidOnlybooleanfalseDrop rows with no live bid; applied to the rows this run reads.
orderBystringfeaturedAsks StockX to order the whole catalogue, so it decides which items you get first.
sortResultsBystringsite_orderRearranges the rows this run collected, after they are read; does not change which items you get.
fetchDetailsbooleanfalse (form prefill is checked)Fetch each item's product page for the style code, colourway, retail price, dates and the complete size table. Charged once per record; the market fields above are on every row either way.
maxItemsinteger20Stop after collecting this many records, split evenly across all search terms or URLs and not rebalanced if one source runs dry early. 0 means unlimited.
maxPagesinteger0Optional safety bound on result pages walked per search term or URL. 0 means no page limit.
resumeFromRunIdstring(none)Continue one interrupted run without returning or billing what it already collected.
incrementalModebooleanfalseReturn only new and changed records on recurring runs of the same search.
stateKeystring(none)Name a monitoring campaign, or deliberately share one across differently configured runs.
emitUnchangedbooleanfalseAlso return, and bill, rows that did not change.
emitExpiredbooleanfalseIncremental mode only. Also detect and return (and bill) rows that disappeared, but only once a run with this on has completed a scan of the tracked scope end to end.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which record pages are created.
maxNotifyListingsinteger50Cap on items exported to each connector per run.
proxyobjectApify ProxyConnection settings. Leave the default; change it only if a run reports it could not read any results.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"rowType": "variant",
"recordId": "a1b2c3d4-2222-4a2b-9c3d-000000000002",
"productId": "a1b2c3d4-1111-4a2b-9c3d-000000000001",
"variantId": "a1b2c3d4-2222-4a2b-9c3d-000000000002",
"title": "Northaven Trailcore 02 Storm Grey Ember",
"brand": "Northaven",
"model": "Northaven Trailcore 02",
"urlKey": "northaven-trailcore-02-storm-grey-ember",
"url": "https://stockx.com/northaven-trailcore-02-storm-grey-ember",
"size": "9",
"sizeType": "us m",
"requestedSize": "US M 9",
"sizeConversions": [
{ "size": "US M 9", "type": "us m" },
{ "size": "UK 8", "type": "uk" },
{ "size": "EU 42.5", "type": "eu" },
{ "size": "CM 27", "type": "cm" },
{ "size": "US W 10.5", "type": "us w" }
],
"lowestAsk": 210,
"lowestAskUpdatedAt": "2026-09-14T03:20:00Z",
"highestBid": 178,
"highestBidUpdatedAt": "2026-09-12T18:05:00Z",
"lastSale": 205,
"bidAskSpread": 32,
"standardAskCount": 54,
"standardLowestAsk": 210,
"expressNextDayAskCount": 9,
"expressNextDayLowestAsk": 228,
"salesLast72Hours": 21,
"salesLast90Days": 640,
"averagePriceLast90Days": 198,
"salesLast12Months": 2100,
"averagePriceLast12Months": 205,
"priceVolatility": 0.087,
"pricePremium": 0.45,
"currency": "USD",
"market": "US",
"releaseDate": "2022-11-05",
"gender": "men",
"productCategory": "sneakers",
"imageUrl": "https://images.stockx.com/images/Northaven-Trailcore-02-Storm-Grey-Ember-Product.jpg",
"scrapedAt": "2026-09-20T09:15:00Z"
}

Plan Requirement

The default connection setting works out of the box, and the run automatically retries with a different connection when one is refused. For large or frequent runs, a higher throughput connection group gives more headroom; pick it under Connection.

FAQ

How much does it cost?

You pay per market record returned (one row, or one size when a size scale is set), plus full product details only when that toggle is switched on. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.

This actor collects only publicly available market data. You are responsible for how you use it: follow StockX's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Ask and bid prices are generally facts, but product photography and descriptions may be subject to third-party rights.

Can I get only new listings or price moves on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated records by default (plus reappeared ones once you also turn on Emit expired), and unchanged ones are not billed unless you ask for them.

Why did my run return fewer rows than I expected?

StockX returns at most 1000 results for any one search or category; a broad scope is truncated there rather than read in full, and the run tells you so. Narrow it with the category, brand, size, colour, price or availability filters, or raise Max items and Max pages. With multiple search terms or URLs, Max items is also split evenly across them and not rebalanced if one comes up short, so a search term with few results doesn't hand its unused budget to the others; the four client-side filters (minimum last sale, minimum recent sales, live-ask-only, live-bid-only) and cross-source deduplication can also leave a run with fewer rows than Max items alone would suggest.

Why did my run fail instead of returning an empty dataset?

If the connection is refused on every request, the run stops with a clear message so "nothing matched" is never confused with "nothing could be read." Run it again in a few minutes, or change the Connection setting. A search that genuinely matches nothing still succeeds, with an explanation instead of rows.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

๐Ÿ”— Want more fashion data?

Pair this actor with these related scrapers from the same team:

๐Ÿ‘— KREAM Korea Scraper
Scrape KREAM (kream.co.kr) sneaker and fashion resale data by keyword search, filters...
๐Ÿ‘— GOAT Scraper
Scrape GOAT (goat.com), the sneaker and streetwear resale marketplace. Search or paste...
๐Ÿ‘— KLEKT Sneaker & Apparel Resale Scraper
Scrape sneaker and streetwear listings from KLEKT (klekt.com). Browse the catalog with...
โšฝ Whatnot Scraper
Scrape Whatnot live and upcoming shows, queued items and lots, and seller profiles...
๐Ÿ‘— SSENSE Scraper
Scrape SSENSE by keyword, category, designer or URL. Every row carries the selling price...
๐Ÿ‘— ASOS Scraper
Scrape ASOS by keyword, category or URL. Every row carries the selling price and the...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support & custom scrapers

  • ๐Ÿž Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • ๐Ÿ› ๏ธ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.