Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the Chrono24 API page →
E-commerce & Marketplaces

Chrono24 API & Scraper

The Chrono24 API returns luxury-watch marketplace data as clean JSON.

3 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary search endpoint returns listings with id, title, price, currency, URL, image and availability, plus an aggregate with low, high and total results, and you can browse and pull a detail. It is built for watch-price intelligence, resale tools and luxury-market analytics that need Chrono24 data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

Chrono24 fields: reference_number vs listing_id, and the numbers that mislead

Watch buyers search by reference number and developers page by listing id, and confusing the two is the most common Chrono24 integration bug. The second trap is the aggregate block, which looks like a summary of your query and is not. Every value below came from live search, browse and detail calls on 2026-08-27.

FieldWhat it isMeasured example
listing_idOne seller's offer. A relisted watch gets a new one46892665, taken from the URL suffix --id46892665.htm
reference_numberThe manufacturer's model reference. Many listings share it, and only detail returns it"16800" for a Rolex Submariner Date
listing_codeAn internal Chrono24 model code returned by detail but absent from the documented field list"RX2M16"
price / currency (detail)Numeric price and its currency7732.0 / "USD"
listings[].currency (search, browse)null on every card measured, 60 of 60use aggregate.currency instead, which returned "USD"
aggregate.total_resultsSite-wide listing count, not the size of your result set671,486 / 671,485 / 671,497 across three unrelated queries
aggregate.low_price / high_priceStrings from the page's aggregate offer that did not match the page's own listingsa price_asc Submariner page whose cheapest card was 5,500 reported low_price "8283"
condition / condition_detailThe filterable token, then the seller's own wording"used" / "Used (Fair) The item shows major, visible signs of wear like scratches and dents."
yearFree text rather than an integer, and it can carry a qualifier"1986 (Approximation)"
scope_of_deliveryBox and papers status; the leading sentence is clean and the tail leaks page markup"No original box, no original papers" followed by escaped HTML
seller_locationA postal-address object with country and city only{"addressCountry": "JP", "addressLocality": "Tokyo"}
availabilityA schema.org availability string"InStock" on all 60 cards measured

search takes free text combining brand, model and reference ("omega 3861") while browse takes a brand slug plus an optional model slug (brand=omega, model=speedmaster). Both return roughly 60 cards per page across pages 1 to 100, and meta.pagination.has_more is the only paging signal worth trusting.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/chrono24/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "rolex submariner"
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "chrono24",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 7406.5,
    "record_count": 60,
    "bytes": 678205,
    "cache_hit": false,
    "completeness_pct": 100,
    "stop_reason": "limit_reached",
    "pagination": {
      "page": 1,
      "has_more": true,
      "next_page": 2
    },
    "listing_source": "canonical",
    "listing_url": "https://www.chrono24.com/rolex/submariner--mod1.htm",
    "charged_credits": 1,
    "version": "1.0.0"
  },
  "data": {
    "listings": [
      {
        "listing_id": "47485793",
        "title": "Rolex Submariner Rolex submariner no date 14060",
        "price": 10150,
        "currency": "USD",
        "url": "https://www.chrono24.com/rolex/submariner--id47485793.htm",
        "image": "https://img.chrono24.com/images/uhren/u9aacprmivqs-z9pfk0zbpo7d2lgo97si0hd7-ExtraLarge.jpg",
        "availability": "InStock"
      },
      {
        "listing_id": "47448287",
        "title": "Rolex Submariner BRAND NEW September 2025 Submariner No Date 124060",
        "price": 13500,
        "currency": "USD",
        "url": "https://www.chrono24.com/rolex/submariner--id47448287.htm",
        "image": "https://img.chrono24.com/images/uhren/47448287-fz4agj1igzaiftxhllq6qlga-ExtraLarge.jpg",
        "availability": "InStock"
      },
      {
        "listing_id": "48481978",
        "title": "Rolex Submariner Date 16613 Rolex Submariner Date Bluesy",
        "price": 9700,
        "currency": "USD",
        "url": "https://www.chrono24.com/rolex/submariner-date--id48481978.htm",
        "image": "https://img.chrono24.com/images/uhren/hmqj994zm3h7-3wrm2zxy8cdwe7qeofvitaem-ExtraLarge.jpg",
        "availability": "InStock"
      }
    ],
    "aggregate": {
      "low_price": "8162",
      "high_price": "301100",
      "currency": "USD",
      "offer_count_on_page": "60",
      "total_results": 9127
    }
  }
}
Actions

What the Chrono24 API does

ActionDescriptionConcrete use caseKey params
searchSearch Chrono24 by free-text keyword (brand + model + reference, e.g. 'rolex submariner', 'omega speedmaster 3861'). Optional filters: price_min/price_max, condition (new/used), movement, year, sort. Paginated (~60/page). Returns listing cards with title, price, currency, condition availability, image and url.Pricing teams call search to search Chrono24 by free-text keyword (brand + model + reference, e.g.query, page, price_min, price_max, condition, ...
browseBrowse all listings for a brand (e.g. brand='rolex') or a brand+model (brand='omega', model='speedmaster'). Same filters and paginated card shape as search — the catalog-discovery surface for a whole brand or model family.Marketplace operators call browse to get browse all listings for a brand (e.g.brand, model, page, price_min, price_max, ...
detailFull watch listing by `url` OR `listing_id`: brand, model, reference number, price, currency, condition (+ condition text), year, movement, case material, case diameter, crystal, strap material, dial, gender, jewels, power reserve, scope of delivery, seller location, delivery estimate, description and all images.Catalog enrichment teams call detail to get full watch listing by `url` OR `listing_id`.url, listing_id
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/chrono24/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"rolex submariner"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.chrono24.search with {"query":"rolex submariner"}.
Use cases

Who uses this API and why

  • Watch-price tools call search to track the market range for a reference across dealers.
  • Resale and investment products use the aggregate low/high to value a specific model.
  • Luxury-market analysts use browse to monitor supply and pricing for a brand or collection.
FAQ

Questions developers ask before integrating

What is the difference between a Chrono24 listing_id and a reference number?

listing_id identifies one seller's offer; reference_number identifies the watch model itself. The measured record shows it clearly: listing_id 46892665 sits at chrono24.com/rolex/rolex-submariner-date--id46892665.htm and carries reference_number "16800", the Rolex reference that hundreds of other listings also carry. Track a specific watch for sale by listing_id, and build a price history for a model by grouping on reference_number. Note that only detail returns reference_number: search and browse cards do not include it, so grouping costs one detail call per listing.

Why is currency null on Chrono24 search and browse results?

It sits at the aggregate level rather than on each card. Measured across 60 cards on 2026-08-27, listings[].currency was null on all 60 while data.aggregate.currency was "USD" for the whole page. The prices themselves are real numbers in that currency. detail does return currency per watch, "USD" alongside price 7732.0, so if you cache cards, take the currency from aggregate and stamp it onto the rows yourself.

Is aggregate.total_results the number of matches for my query?

No, and this is worth knowing before you build a market-size report on it. Three unrelated queries measured on 2026-08-27 returned total_results 671,486 ("rolex submariner" filtered to used at 2,000 to 15,000), 671,485 (browse omega speedmaster) and 671,497 (browse rolex, condition new). That is the site-wide listing count drifting with the marketplace, not your result set. Page with page and meta.pagination.has_more instead, and if you need a count for a query, count what you actually fetch.

Can I trust aggregate.low_price and high_price as the price range of my results?

Not as the range of the cards you received. They are strings lifted from the page's aggregate offer block, and on a price_asc-sorted Submariner search whose cheapest card was 5,500 the aggregate reported low_price "8283" and high_price "15700". A browse of Omega Speedmaster reported "1674" to "587700". They are directionally useful for the model family but they do not describe your page. Compute min and max from listings[].price when the number matters.

How do I tell whether a watch comes with its box and papers?

Through scope_of_delivery on the detail action, and you have to trim it. The measured record began "No original box, no original papers" and then trailed off into escaped page markup from the tooltip that explains the field. Take the text up to the first "Original box" or the first escaped angle bracket and treat the remainder as noise. There is no separate boolean for box or papers, so a text match on "no original box" and "no original papers" is the honest way to derive one.

Does the API say whether the seller is a dealer or a private seller?

Not on the record measured on 2026-08-27. detail returned seller_location as a postal-address object with addressCountry "JP" and addressLocality "Tokyo" and nothing else about the seller: no name, no dealer or private flag, no trust badge, no years-active figure. The closest shipping signal is delivery_estimate, which came back as free text ("Anticipated delivery: 8/28 - 9/8"). If seller type matters to your product, treat it as data this API does not currently expose rather than assuming a field you have not seen in a response.

Why did detail return TARGET_BLOCKED when search worked fine?

Individual listing pages are guarded more tightly than result pages. Measured on 2026-08-27, four detail attempts on listing 46892665 produced two full records in 1.7 and 2.1 seconds and two TARGET_BLOCKED errors with error.retryable: true, while search and browse against the same engine succeeded every time. Treat a retryable TARGET_BLOCKED as an instruction to repeat the call, not as evidence that the listing is gone. Returning a clean error beats returning a half-parsed record that looks real.

What format is the year field, and how does it relate to the year filter?

They are not the same type. The year parameter on search and browse is an integer between 1900 and 2030. The year field returned by detail is free text and can carry a qualifier: the measured record returned "1986 (Approximation)", not 1986. Parse it as a string, pull the leading four digits, and keep the qualifier if you display the value, since "Approximation" is a meaningful caveat on a vintage watch.

What is the Chrono24 API?

Chrono24 API is a ReefAPI endpoint group for chrono24 It returns live JSON through POST requests under /chrono24/v1.

Is the Chrono24 API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Chrono24 calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Chrono24 login or account?

No login to Chrono24 is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Chrono24 data?

The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Chrono24 API use?

Chrono24 actions currently cost 1 credit per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.

Can I call Chrono24 from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call chrono24 actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / chrono24

Chrono24

Chrono24

base /chrono24/v13 endpoints
post/chrono24/v1/browse1 credit

Browse all listings for a brand (e.g. brand='rolex') or a brand+model (brand='omega', model='speedmaster'). Same filters and paginated card shape as search — the catalog-discovery surface for a whole brand or model family.

ParameterAllowed / rangeDescription
brandrequired—Watch brand to browse (rolex, omega, patek-philippe, audemars-piguet, tudor, cartier, ...).
modeloptional—Optional model/family within the brand (submariner, speedmaster, nautilus, ...).
page = 1optional1–100Result page (~60 listings per page). Page until meta.pagination.has_more is false.
price_minoptional0–Minimum price filter (in the listing currency, USD).
price_maxoptional0–Maximum price filter (in the listing currency, USD).
conditionoptionalnew · used · incompleteFilter by watch condition.
movementoptionalautomatic · manual · quartzFilter by movement type.
yearoptional1900–2030Filter to watches produced in this year.
sort = relevanceoptionalrelevance · price_asc · price_desc · newestResult ordering.
Try in playground →
post/chrono24/v1/detail1 credit

Full watch listing by `url` OR `listing_id`: brand, model, reference number, price, currency, condition (+ condition text), year, movement, case material, case diameter, crystal, strap material, dial, gender, jewels, power reserve, scope of delivery, seller location, delivery estimate, description and all images.

ParameterAllowed / rangeDescription
urloptional—Full Chrono24 listing URL (from a search/browse result).
listing_idoptional—Chrono24 listing id (the number in --id<N>.htm). Provide url OR listing_id.
Try in playground →
Built for volume
5M+ requests a day

Measured at 60 requests a second across the fleet, with no central bottleneck. Volume pricing is on request, and per-key limits are raised for high-volume accounts.

Missing a source?
We build it

Tell us a site we do not cover yet and it becomes an engine. A customer asked for bestprice.gr on a Sunday and it was in the catalog the next day.

Support
2 minute median reply

Median time from a question in the live chat to the first answer, measured across every answered conversation. Setup help included, no support tier to buy.

One key, one balance
Every API included

No per-site plans and no separate subscriptions. One key and one credit pool across the whole catalog, so adding a source costs nothing up front.

Planning something large? Tell us the volume and the sources and we will come back with what it costs and what we would have to build.