Catawiki Sold Prices Scraper avatar

Catawiki Sold Prices Scraper

Pricing

from $2.25 / 1,000 lot results

Go to Apify Store
Catawiki Sold Prices Scraper

Catawiki Sold Prices Scraper

Get Catawiki sold prices and past auction results by keyword: final price, sold or unsold, reserve status, and optional expert estimates. History back to 2020, a tracker for new sales, lot ID lookups, and live bids. No Catawiki account needed.

Pricing

from $2.25 / 1,000 lot results

Rating

0.0

(0)

Developer

Phantom Coder

Phantom Coder

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Get closing prices from Catawiki's closed auction lots by keyword or by lot ID, with sold/unsold status, reserve info, and optional specs, expert estimates, and seller data. No Catawiki account or API key required.


Who is this for

  • Collectors and dealers (trading cards, coins, watches, comics) checking what a specific item actually sold for on Catawiki before bidding on a similar one
  • Pricing and market research teams building a sold-price history for a category or keyword that Catawiki's own site does not expose in bulk
  • Arbitrage buyers comparing a live listing's current bid against recent closed-lot sold prices for the same keyword
  • Appraisers and insurers pulling expert estimates and specifications for comparable closed lots

Why it's different

Most Catawiki tools track live auctions: current bids, estimates, and end-of-auction alerts. This Actor is built for closing and sold prices. Catawiki keeps final prices for closed lots for years (in testing, lots that closed in 2020 still returned prices), but nothing on the site lets you browse that history by keyword - you need the exact lot ID.

This Actor closes that gap: give it a keyword like "rolex submariner", and it scans Catawiki's closed-lot index, prices every candidate, and returns only the lots that actually sold (or, optionally, closed without a sale). For example, from a real run:

title: "Rolex - Submariner Date - Ref. 16610 - Men - 2006"
status: "sold" finalPrice: 7900 currency: "EUR" biddingEndTime: "2026-08-30T12:07:30.000Z"

What you get

  • Sold prices by keyword - scans Catawiki's closed-lot index and returns final prices for matching lots
  • Unsold closed lots (optional) - lots that closed without meeting reserve, clearly separated from real sales
  • Specific lot lookups - price and describe exact lot IDs or URLs you already have, any status
  • Live/open lot prices - current highest bid for lots still being bid on, by keyword
  • Track new sales - remembers open lots matching your keywords and reports each one's final price once it closes, filling the gap the closed-lot index leaves for recent sales
  • Lot details add-on - specifications, expert estimate, seller ID/country/score, and a plain-text description, for lots young enough that Catawiki still serves them

How to use

  1. Pick a mode: "Sold prices" to search by keyword, "Specific lot IDs" if you already have lot IDs or URLs, "Live/open lots" for current auctions, or "Track new sales" to catch sales the closed-lot index hasn't indexed yet.
  2. For "Sold prices", "Live/open lots", or "Track new sales", add one or more keywords - every word must appear as a whole word in the lot's title (so "psa 10" never matches "psa 100").
  3. Set max results per keyword, and turn on include unsold if you also want closed-but-not-sold lots.
  4. Turn on include lot details ($) if you want specifications, expert estimates, and seller info - it costs one extra page load per lot.
  5. Click Start, then open the dataset.

⚠️ "Sold prices" mode finds lots through Catawiki's closed-lot index, which doesn't include lots from the last 6 or so weeks (see Limitations). A keyword with 0 results most often means nothing matching has closed yet in the indexed window, not that the Actor failed - check the run log, which always says when a keyword matched nothing. For recent sales, use "Track new sales" instead.

Tracking new sales

"Track new sales" mode closes the gap left by the closed-lot index: it remembers every open lot matching your keywords and reports each one's final price as soon as it closes, without waiting for the index to catch up.

  • Schedule it to run regularly (daily is best) - each run prices the lots it's already tracking, drops any that closed, and starts tracking new open lots it finds.
  • Run "Sold prices" mode once first for history, then switch to "Track new sales" to keep it current going forward.
  • One tracker per keyword and exclude-words combination - changing the exclude words starts a new tracker, and the lots the old one was watching are no longer checked. Pick your exclude words before you schedule.
  • The first run for a new keyword only starts tracking open lots - it won't have anything to report until a later run, once those lots close.

Input configuration

FieldTypeDefaultDescription
modestringsoldsold, lotIds, live, or track
keywordsarray["charizard psa 10"]Search terms (sold/live/track modes); every word must match as a whole word
lotIdsarraynoneLot IDs or lot URLs (lotIds mode)
currencystringEUREUR, USD, or GBP - which currency highestBid/finalPrice are shown in
maxResultsPerKeywordinteger100Max qualifying lots per keyword (1-5000); in track mode, the max open lots tracked per keyword
excludeWordsarraynoneSkip lots whose title contains any of these whole words (sold/live/track modes)
includeUnsoldbooleanfalseAlso return closed-but-unsold lots (not applicable to lotIds mode, which always returns every status)
soldAfterstringnoneOnly lots whose bidding ended on/after this date (YYYY-MM-DD); sold mode only
soldBeforestringnoneOnly lots whose bidding ended on/before this date (YYYY-MM-DD); sold mode only
includeDetailsbooleanfalseAdd-on ($): specs, expert estimate, seller info, description
proxyConfigurationobject{ "useApifyProxy": true }Apify datacenter proxy (default, verified working) or residential as a fallback
{
"mode": "sold",
"keywords": ["charizard psa 10"],
"currency": "EUR",
"maxResultsPerKeyword": 50,
"includeUnsold": false,
"includeDetails": false
}

Output

One flat row per lot. Every row has the same fields regardless of status; add-on fields appear only when includeDetails is on.

A sold lot:

{
"lotId": 106222753,
"url": "https://www.catawiki.com/en/l/106222753-rolex-submariner-date-ref-16610-men-2006",
"title": "Rolex - Submariner Date - Ref. 16610 - Men - 2006",
"status": "sold",
"sold": true,
"closed": true,
"finalPrice": 7900,
"highestBid": 7900,
"currency": "EUR",
"priceEUR": 7900,
"priceUSD": 9168,
"priceGBP": 6763,
"reservePriceMet": true,
"biddingStartTime": "2026-08-21T10:00:00.000Z",
"biddingEndTime": "2026-08-30T12:07:30.000Z",
"auctionId": 1272898,
"favoriteCount": 37,
"imageUrl": "https://assets.catawiki.nl/assets/2026/8/6/4/0/4/4046bab3-5b39-42f5-ad3f-21d65f6e41c7.jpg",
"thumbnailUrl": "https://assets.catawiki.nl/assets/2026/8/6/4/0/4/thumb2_4046bab3-5b39-42f5-ad3f-21d65f6e41c7.jpg",
"keyword": "rolex submariner",
"scrapedAt": "2026-10-25T17:03:20.404Z"
}

A closed, unsold lot (includeUnsold: true, key fields only). Bidding reached €13,500, but the reserve wasn't met, so there was no sale:

{
"lotId": 106724125,
"title": "Rolex - Day-Date - 18308 - Unisex - 1991",
"status": "unsold",
"sold": false,
"closed": true,
"finalPrice": null,
"highestBid": 13500,
"currency": "EUR",
"reservePriceMet": false,
"biddingEndTime": "2026-09-15T16:11:50.000Z"
}

An open lot (live mode, currency: "USD", key fields only):

{
"lotId": 107907234,
"title": "Pokémon - 1 Graded card - Charizard 009/049 Foil - CGC 10 - Various sets",
"status": "open",
"sold": null,
"closed": false,
"finalPrice": null,
"highestBid": 7,
"currency": "USD",
"reservePriceMet": null,
"biddingEndTime": "2026-11-01T20:51:55.000Z"
}

With includeDetails: true, a lot also carries (from a real run; seller fields sellerId, sellerCountry, and sellerScore left out here):

{
"detailsAvailable": true,
"subtitle": "Japanese",
"categoryId": 1465,
"categoryName": "Pokemon Cards",
"expertEstimateMin": 380,
"expertEstimateMax": 450,
"expertEstimateCurrency": "EUR",
"specifications": [{ "name": "Grade", "value": "10" }, { "name": "Type", "value": "Graded card" }],
"description": "2022 Pokémon GO Radiant Pokémon Set – Radiant Venusaur, Charizard, Blastoise & Eevee – PSA Gem Mint 10 (4 Cards) Offered..."
}

A lot too old for details (includeDetails: true, but the detail page has redirected away):

{
"detailsAvailable": false
}

No match for a keyword (not an error - the run still succeeds):

The dataset simply has no row for that keyword, and the run log reads No closed lots matched "<keyword>".


Understanding the data

  • status and sold always travel together: status: "sold" means sold: true; status: "unsold" means sold: false (closed, but no winner - the reserve wasn't met); status: "open" means sold: null (not decided yet).
  • finalPrice is only ever set for a sold lot. highestBid is set for every status - it is the current bid for an open lot, and the winning bid for a sold or unsold lot. Read highestBid together with reservePriceMet for an unsold lot: a high highestBid with reservePriceMet: false tells you the seller's reserve was set above what bidders were willing to pay.
  • priceEUR/priceUSD/priceGBP are always all three present, regardless of the currency input - highestBid/finalPrice just point at whichever one you asked for, so you don't need to re-run the Actor to compare currencies.
  • keyword is null in lotIds mode. In sold mode, a lot that matches two keywords is returned once, credited to the first keyword in your list, and billed once.

Common use cases

  • Price-check before bidding: run lotIds mode on the open lot's ID plus a handful of past sold lots found via a keyword search, and compare highestBid on the open lot against the median finalPrice of the last 10 sold matches.
  • Build a niche's sold trend: run sold mode once for a keyword like "rolex submariner" with maxResultsPerKeyword: 200 and chart finalPrice over biddingEndTime, then schedule track mode daily to keep the chart current without paying for the same lots twice.
  • Spot overpriced reserves: run with includeUnsold: true and filter for status == "unsold" - a cluster of unsold lots for the same keyword suggests sellers are pricing above what the market pays.
  • Comparable-sales research with context: turn on includeDetails and filter sold lots where finalPrice is more than 20% below expertEstimateMin, to find items that sold for less than Catawiki's own expert expected.
  • Cover recent sales the index misses: schedule track mode daily for a keyword, so new sold prices show up as soon as a lot closes, instead of waiting 6-10 weeks for sold mode's closed-lot index to catch up.

FAQ

Do I need a Catawiki account? No - everything here is scraped logged out.

Why did my keyword return 0 results? Either no matching lot closed early enough to be in Catawiki's closed-lot index yet (see Limitations), or the keyword's tokens are too specific - remember matching is whole-word AND, so "psa 10" only matches a lot with both "psa" and "10" as separate words in its title, not "psa 100".

How recent can "sold" results be? Catawiki adds lots to its closed-lot index gradually. In an October 2026 check of about 2,000 lots, the index held nearly all lots closed 10 or more weeks earlier, part of those closed 6-10 weeks earlier, and almost none from the last 6 weeks. Sold lots appear later than unsold ones. For a lot that closed recently and whose ID you know, use lotIds mode: prices are available right after a lot closes.

Why is detailsAvailable: false on some lots? Catawiki's lot detail page redirects to a category page once a lot has been closed for roughly 6 months or more. The price and status fields stay available indefinitely; only the specs/estimate/seller/description add-on fields are affected.

Why are some results far cheaper than the rest? Matching is on the lot title, so anything titled with your keywords counts. In a real "rolex submariner" run, art prints, an enamel advertising sign, and a LEGO piece sold for €17-50 next to watches at €7,000+. Add excludeWords to keep comps clean. In that run, the non-watch lots had titles with words like art, sign, lego, banksy, plate, and box. Check the cheapest rows of your first run to see which words your keyword needs.

Can I get bid history? No - Catawiki's bid-history endpoint returns nothing when logged out, even for lots that clearly had bids, so this is not implemented.

Why did my first track run return nothing? That's expected, not a failure. The first run for a keyword only has open lots to find - it starts tracking them and the run log says so, with a status message like "Now tracking 40 open lot(s)...". Final prices appear on the next scheduled run, once those lots actually close.

How are results ordered and picked? Within a keyword, the Actor picks the lots with the highest lot IDs first, because Catawiki assigns IDs roughly in order, so higher IDs are usually more recent. The picked lots are then output sorted by biddingEndTime, newest first. With a large keyword (for example "pokemon", 70,000+ closed lots) and a small maxResultsPerKeyword, you get a recent slice, not every match.

Limitations

  1. Recent sales are missing from keyword search: "Sold prices" mode finds lots through Catawiki's closed-lot index, which is near-complete only for lots closed about 10 or more weeks ago, partial for 6-10 weeks, and nearly empty for the last 6 weeks (measured October 2026; sold lots lag more than unsold ones). History goes back to 2020. Use lotIds mode to price a specific recently closed lot.
  2. Approximate recency ordering: "newest first" within a keyword is based on lot ID, not the exact biddingEndTime - treat it as roughly, not exactly, ordered.
  3. No bid history: only the final/current price is available, not the sequence of bids.
  4. Lot details age out: specifications, expert estimate, seller info, and description stop being available once a lot's page redirects away (roughly 6+ months after closing). Price and status fields are not affected by this.
  5. No category filter yet: matching is keyword/title-based only; there is no category ID filter in this version.
  6. Datacenter proxy dependency: this Actor is verified against the Apify datacenter proxy. If Catawiki changes its blocking behavior, switch proxyConfiguration to residential.
  7. "Track new sales" mode's run spacing matters: a lot that opens and closes entirely between two runs can be missed if runs are more than about 5 days apart. Running two instances of the same tracker (same keyword and exclude words) at the same time can also overwrite each other's state - schedule one run at a time per tracker.

Pricing

Pay-per-event pricing. You pay for the lots you get, never for lots that weren't returned. Prices per 1,000 events:

EventWhen it's chargedFreeStarterScaleBusiness and above
Lot resultOnce per lot returned (sold, unsold, or open). In track mode, once per tracked lot whose final result is returned$3.00$2.75$2.50$2.25
Add-on: Lot detailsOnce per lot whose detail fields were returned$6.00$5.50$5.00$4.50

On top of that, each run has a fixed Actor start fee of $0.00005 on every plan.

Typical costs on the Free plan:

  • 50 sold Rolex Submariners: about $0.15
  • 200 sold Pokémon lots with details: about $1.80
  • A daily track run for one keyword that returns 5 newly closed lots: about $0.015 per day, or about $0.45 per month

A run that can't reach Catawiki at all (every session blocked) is charged only the Actor start fee, never for results.

Output field reference

FieldDescription
lotIdNumeric Catawiki lot ID
urlLot page URL
titleLot title (falls back to a title built from the URL slug if unavailable)
statussold, unsold, or open
soldtrue/false for a decided lot, null while still open
closedWhether bidding has ended
finalPriceSale price in the chosen currency; set only when status is sold
highestBidCurrent/final highest bid in the chosen currency, for every status
currencyThe currency highestBid/finalPrice are shown in
priceEUR / priceUSD / priceGBPHighest/final bid amount in each currency, always present
reservePriceMetWhether the reserve price was met. null means the lot had no reserve (common for "no reserve price" lots) or is still open
biddingStartTime / biddingEndTimeISO 8601 timestamps
auctionIdNumeric Catawiki auction ID
favoriteCountNumber of users who favorited the lot
imageUrl / thumbnailUrlLot images
keywordThe keyword that found this lot (null in lotIds mode)
scrapedAtWhen this row was scraped, ISO 8601
detailsAvailableAdd-on: whether detail fields below were returned
subtitleAdd-on: lot subtitle
categoryId / categoryNameAdd-on: Catawiki category
expertEstimateMin / expertEstimateMaxAdd-on: Catawiki expert's estimate range, in expertEstimateCurrency
expertEstimateCurrencyAdd-on: currency of the estimate. Catawiki often sets the estimate in one currency only, so this falls back to EUR when the chosen currency has none
sellerId / sellerCountry / sellerScoreAdd-on: seller info - ID, country, and feedback score only
specificationsAdd-on: array of { name, value } spec pairs
descriptionAdd-on: plain-text description, HTML stripped, truncated to about 5,000 characters

Support

Questions or issues? Open a ticket in the Issues tab on the Actor page.