Grailed Scraper - Listings, Prices, Sellers & Reviews
Pricing
from $1.90 / 1,000 listing, seller or review records
Grailed Scraper - Listings, Prices, Sellers & Reviews
Scrape Grailed by keyword, category, designer, condition, size or URL. Extract prices and price history, descriptions, measurements, shipping, seller profiles and reviews. Includes change tracking to monitor new, updated and removed listings.
Pricing
from $1.90 / 1,000 listing, seller or review records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Grailed Scraper: Listings, Ask Prices & Seller Profiles
Grailed Scraper turns Grailed, the menswear and streetwear resale marketplace, into a clean dataset. Get listings with the current ask price and the store's own ask history (every prior asking price on a listing), seller profiles with their rating average, rating count and rating tags, and seller reviews. Search by keyword, walk the store's own department, category, designer, condition and size facets, watch specific sellers, or paste any store URL, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Four ways to find listings. Search by keyword, walk any combination of the store's own facets (department, category, designer, condition, size, price), watch named sellers, or paste store URLs directly.
- Ask price and ask history on every row. Each listing carries the store's own record of every prior asking price, so a price cut is visible, not just the current number.
- Listing detail on demand. Switch on Fetch listing details for the description, measurement table, photo set and deeper seller fields, only when you need them, billed only then.
- Sellers, reviews and closets. Read a seller's profile, pull their reviews as their own rows, or walk their whole on-sale closet like a normal search.
- Built for monitoring. Incremental mode returns only new, updated and reappeared listings on repeat runs, treats an ask price move as a real change (not noise), and a refused run fails loudly instead of returning an empty dataset.
- URL mode for direct control. Paste a single listing, a category, a designer, a search page or a seller profile URL and it is read exactly as scoped, with page and price filters still applying.
- Resume support. Continue an interrupted crawl from a previous run without returning or paying for records it already collected.
Use Cases
- Resale price research: track ask price moves and the store's own price-drop history across designers and categories to spot markdowns and value.
- Sourcing and reselling: monitor specific categories, designers or sizes for new listings the moment they post.
- Seller and reputation research: pull a seller's profile, rating average, rating tags and reviews before buying or partnering.
- Marketplace analytics: build historical datasets of listings, prices and conditions for trend and demand analysis.
- Personal shopping alerts: schedule Incremental mode against a saved search and get only what is new or changed.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
recordId / rowType | "00000001" / "product" (also "seller", "review") |
listingId | "00000001" |
title / designer | "Sample Wool Sweater" / "Sample Designer" |
price | 210.0 |
originalPrice / askHistory | 260.0 / [260.0, 235.0, 210.0] |
size / condition / conditionLabel | "m" / "is_gently_used" / "Gently Used" |
categoryPath / department | "tops.sweaters_knitwear" / "menswear" |
sold / soldAt / soldPrice | false / null / null |
sellerUsername / sellerRating / sellerRatingCount / sellerSales | "sample_seller_00" / 4.9 / 32 / 64 |
coverPhoto / shippingUs | cover image URL / 12.0 |
buyNow / makeOffer | true / true |
styles / badges | ["luxury"] / [] |
url | link to the listing, seller or category page |
description / measurements / photos | full text, the measurement table, photo URLs (with Fetch listing details on) |
sellerSince / sellerLocation / sellerListingsForSale | seller-page fields (with Fetch listing details on) |
changeType / changedFields / firstSeenAt / lastSeenAt | Incremental mode change tracking fields |
scrapedAt | "2026-01-01T00:00:00Z" |
Seller rows carry the full profile instead (rating average, count and tags, trusted/verified/quick-responder/speedy-shipper flags, location, member since, purchase count). Review rows carry the rating, the note, the tags and the listing the review refers to.
How to Use
- Pick a mode:
search(by keyword and facets) orurl(paste Grailed links). - In search mode, add search terms and narrow with the department, category, designer, condition, size and price facets, or name sellers to read their profiles. In URL mode, paste listing, category, designer, seller or search URLs instead.
- Turn on Fetch listing details if you want the description, measurement table and photos on every row.
- Set Max items to control run size and cost, then click Start.
Search by keyword and facets:
{"mode": "search","searchTerms": ["varsity jacket"],"categories": ["outerwear"],"conditions": ["gently used"],"maxItems": 50}
Read a seller with their reviews and closet:
{"mode": "search","searchTerms": [],"sellerUsernames": ["sample_seller_00"],"fetchSellerReviews": true,"includeSellerListings": true,"maxItems": 50}
Paste store URLs:
{"mode": "url","urls": ["https://www.grailed.com/categories/footwear","https://www.grailed.com/listings/00000001"],"maxItems": 40}
Price watch with Incremental mode:
{"mode": "search","searchTerms": ["Rick Owens jacket"],"minPriceUsd": 100,"maxPriceUsd": 800,"incrementalMode": true,"stateKey": "rick-owens-jacket-watch"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/grailed-marketplace-scraper").call(run_input={"mode": "search", "searchTerms": ["varsity jacket"], "maxItems": 50})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["title"], row["price"], row["sellerUsername"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/grailed-marketplace-scraper').call({ mode: 'search', searchTerms: ['varsity jacket'], 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.
How the page bound and Max items shape a run
The store's own listing feed serves at most 25 pages of 40 rows per scope (1000 rows), the same ceiling its own website lives with; Max pages is an optional extra safety bound per source, off by default. Reaching deeper into a large catalogue means narrowing the scope with more facets, not raising the page bound. Max items is the single cap shared across every search term, seller and URL in one run; set it to 0 for unlimited. Each source gets an even share of it (Max items divided by the number of sources, rounded up), and a source that runs out of results early does not pass its unused share on, so a run whose first term has only a handful of matches can end below Max items.
Max pages counts the store's own page numbers from page 1, not pages walked from where a pasted URL starts. A URL ending in ?page=3 with Max pages set to 2 reads nothing and reports that nothing matched; leave Max pages at 0 or set it above the start page.
In Incremental mode, each source's share counts listings scanned, not listings returned: unchanged listings are suppressed but still use up the share. The store serves listings in its own ranking, not newest first, so a scheduled run with a small Max items looks at the same top slice every time and never reaches a new or repriced listing ranked below it. For monitoring, set Max items well above the number of listings your search matches, or 0.
That sharing has one sharp edge worth knowing: when Max items caps a run mid-page, every row the actor looked at on that page counts as collected, including the rows the cap left no room to keep. If a run combines several overlapping search terms or seller scopes and the first one gets capped on a page that a later term would also have matched, the later term will not offer those rows again, since they already look handled. For example, running the search terms "coat" and "jacket" together with a small Max items can return fewer rows than Max items even though both terms still have unseen matches, because "coat"'s capped page silently claimed listings "jacket" would also have returned. Workaround: give a broad or overlapping search term its own run (or its own generous Max items), or raise Max items enough that a shared page clears in one pass before the run moves to its next term or seller.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips every record it already collected there, so you don't pay twice. - Incremental mode (
incrementalMode) is for scheduled runs over the same search, sellers or URLs. Each row is classifiedNEW,UPDATED(withchangedFields; an ask price move is reported as UPDATED, since on a resale marketplace it is the signal, not noise),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEAREDorEXPIRED(only after a run that scanned the whole tracked scope, and only withemitExpired).stateKeynames or shares the stored state. With Incremental mode off, output is exactly as before.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where record pages should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | How to start the scrape: search runs store searches; url processes the pasted store URLs (the search-mode facets do not apply there). |
searchTerms | array | ["varsity jacket"] | Search mode only. Each term is walked as its own scope with the facets below applied. |
sellerUsernames | array | (none) | Search mode only. Read each named username as a seller profile; the two toggles below add its reviews and its on-sale listings. |
fetchSellerReviews | boolean | false | Search mode only. Read each named seller's reviews as their own rows (rowType review). |
includeSellerListings | boolean | false | Search mode only. Also walk each named seller's on-sale listings as normal product rows. |
categories | array | ["outerwear"] | Search mode only. Only browse these categories; a name the store does not serve stops the run with a clear message. |
designers | array | (none) | Search mode only. Only browse these designers, by the store's own name. |
conditions | array | (none) | Search mode only. Only browse these conditions: new, gently used, used or worn. |
sizes | array | (none) | Search mode only. Only browse these sizes, exactly as the store labels them. |
urls | array | ["https://www.grailed.com/categories/footwear"] | URL mode only. Paste listing, search, category, designer or seller profile URLs; add ?page=3 to a browse URL to start walking from that page. |
department | string | menswear | Which storefront department to read. Applies in both modes. |
minPriceUsd | integer | (none) | Only keep listings whose current ask price is at least this many US dollars. Applies in both modes. |
maxPriceUsd | integer | (none) | Only keep listings whose current ask price is at most this many US dollars. Applies in both modes. |
sortResultsBy | string | site_order | Arranges the rows this run collected, after they are read. Applies in both modes. |
fetchDetails | boolean | false | Fetch each listing's own page for the description, the measurement table, the photo set and the deeper seller fields. Charged once per record. |
maxItems | integer | 20 | The single cap on this run: stop after collecting this many records across every search term, seller and URL. Set 0 for unlimited. |
maxPages | integer | 0 | Safety bound on feed pages walked per search term, seller or URL. 0 means no separate page limit. |
resumeFromRunId | string | (none) | Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. |
incrementalMode | boolean | false | Turn on for recurring monitoring of the same search: later runs return only NEW, UPDATED and REAPPEARED records. |
stateKey | string | (none) | Name or share a monitoring campaign's stored state. Leave empty to derive one automatically from the search, URLs, sellers and filters. |
emitUnchanged | boolean | false | Also return (and bill) records that have not changed since the last run. |
emitExpired | boolean | false | Also return (and bill) records no longer found, once a run has fully scanned the tracked scope. |
mcpConnectors | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which record pages are created. |
maxNotifyListings | integer | 50 | Cap on records written to each connector per run. |
proxy | object | Apify Proxy | Connection settings. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"recordId": "00000001","rowType": "product","listingId": "00000001","url": "https://www.grailed.com/listings/00000001-sample-designer-sample-wool-sweater","title": "Sample Designer Sample Wool Sweater","designer": "Sample Designer","designers": ["Sample Designer"],"price": 210.0,"originalPrice": 260.0,"askHistory": [260.0, 235.0, 210.0],"sold": false,"size": "m","condition": "is_gently_used","conditionLabel": "Gently Used","categoryPath": "tops.sweaters_knitwear","department": "menswear","buyNow": true,"makeOffer": true,"coverPhoto": "https://images.example.com/sample-sweater.jpg","shippingUs": 12.0,"sellerUsername": "sample_seller_00","sellerUrl": "https://www.grailed.com/sample_seller_00","sellerRating": 4.9,"sellerRatingCount": 32,"sellerSales": 64,"scrapedAt": "2026-01-01T00:00:00Z"}
Plan Requirement
The default proxy setting works out of the box, and the actor rotates connections automatically when one is refused. For large or frequent runs, the residential proxy group gives more headroom; pick it under Connection.
FAQ
How much does it cost?
You pay per record returned, plus the listing details surcharge only when Fetch listing details is on. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.
Is it legal to scrape Grailed?
This actor collects only publicly available marketplace data. You are responsible for how you use it: follow Grailed's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing photos and designer names may carry their own rights separate from the plain facts (price, size, condition) attached to a listing.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared records, and unchanged ones are not billed unless you turn on Emit unchanged. Unchanged listings still count toward each source's share of Max items, so give a monitoring run a Max items above the size of the search (or 0), otherwise listings ranked below that slice are never checked.
Why did a run with several search terms return fewer rows than I expected?
Every search term, seller and URL in one run shares a single Max items budget and a single dedup check. When the budget caps a walk mid-page, every row on that page is marked as handled, even the ones the cap left no room to keep. A later, overlapping search term or seller scope in the same run then treats those rows as already collected and does not offer them again, so the total can land below Max items even though the store still has matching listings. Run heavily overlapping searches on their own, or raise Max items so a shared page clears before the run moves on.
Why did my run fail instead of returning an empty dataset?
If the store refuses every request, the run stops with a clear message so "nothing matched this search" is never confused with "nothing could be read". Run it again in a few minutes, or change the Proxy configuration. If only some URLs, listings or sellers could not be read, you still get what was found.
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.
๐ More scrapers you might like
Pair this actor with these related scrapers from the same team:
| ๐ 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... |
| ๐ The RealReal Scraper Scrape luxury consignment listings from therealreal.com. Browse by designer, category or... | ๐ Depop Scraper From $1/1K. Scrape Depop search results, listings, shops, and reviews to JSON, CSV, or... |
| ๐งฉ eBay Scraper Scrape eBay by keyword, category, seller or pasted link across 16 country storefronts... | ๐ Mercari Japan Scraper From $0.80/1K. Scrape Mercari Japan listings, sellers and reviews at scale. Extract... |
๐ 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.