Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the TruckScout24 API page →
docs / truckscout24

TruckScout24

TruckScout24

base /truckscout24/v17 endpoints
post/truckscout24/v1/detail3 credits

One listing in full, by id. Returns the vehicle or machine (type, manufacturer, model, year, condition, functionality, hour meter, odometer, the seller's own vehicle number), the price with its previous price, gross figure, VAT treatment and incoterm, every technical property the seller typed — grouped the way the source groups them, each with a parsed number and unit — the boolean equipment badges, the offer block (listing code, reference number, last update, and an auction's start and end), the seller's street, postcode, town and country, the dealer id with their member-since year, listings online and trust seal, the category breadcrumb, every gallery image and the full description with the injected decoy line removed. The price is cross-checked against the page's own schema.org product data and any disagreement is reported, not hidden.

ParameterAllowed / rangeDescription
listing_idrequired—The listing's numeric id. Accepted as the plain number (21924313), with the source's own 'A' prefix, in its dashed display form (219-24-313 / A219-24-313) or as a full listing URL ending in /tsp/ts-21924313. Get ids from `search`.
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
Try in playground →
post/truckscout24/v1/categories1 credit

The marketplace's own category tree with live per-category listing counts: the nine top-level sectors (transport & commercial vehicles, construction plant, forklifts & warehouse equipment, agricultural, caravans & motorhomes, municipal technology, warehouse technology, recycling, workshop equipment) with the numeric ids every other action's `category_id` takes. Pass a `category_id` to drill into that sector's children — the FULL list the source publishes, not its 'top' shortlist — which is how you get from 9,535 construction machines to the 2,053 excavators or the 1,819 access platforms. Every count is the source's own live figure.

ParameterAllowed / rangeDescription
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
category_idoptional1–Browse one category using the source's own numeric id, at ANY level of the tree (8 = construction plant, 105 = excavators, 7 = transport & commercial vehicles, 246 = flatbed/curtain-side trucks, 252 = tractor units, 42 = forklifts & warehouse equipment, 4 = agricultural, 2357 = caravans & motorhomes). Measured to bite at every level: 8 → 9,535, 132 → 645. Get the ids from the `categories` or `suggest` action, or from any `ts-cat-<id>` URL. Combines with `query` and every filter.
Try in playground →
post/truckscout24/v1/facets2 credits

The source's own live filter counts for a query: which categories, sub-categories, manufacturers, countries, regions, conditions, fuel types, emission classes, gearbox types, suspensions, colours, mast types and axle configurations have stock, and how much. This is how you learn the exact spelling a filter wants (the source is case sensitive and wants region NAMES, not codes) and how to narrow a query that is deeper than the 200-row retrievable ceiling. The source publishes its top 15 per checkbox group. 🔴 The radius bands it also prints are NOT returned: their counts are computed from the caller's own location, which for an API is the server's.

ParameterAllowed / rangeDescription
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
queryoptional—Free-text keyword, exactly as typed into the source's own search box: a vehicle or machine type ('bagger', 'sattelzugmaschine', 'excavator'), a manufacturer, a model, or several words. 🔴 A MULTI-WORD QUERY WIDENS, IT DOES NOT NARROW, unless you also pass `strict_search=true`: the source splits on spaces and matches ANY token. Measured: 'liebherr a 312' returns 55,623 listings loose and exactly 2 with `strict_search=true`; 'bagger liebherr' 2,757 against 'bagger' alone 2,463; 'zzz-no-such-machine-anywhere-xyz' 8,617. A single unmatched word is an honest empty answer ('xyzzyplughfoo' → total 0, zero rows). Any multi-word query sent without `strict_search` comes back with a warning in meta saying so.
strict_search = falseoptional—Require ALL the words of `query` to match instead of any one of them. The default is the source's own (off) so your totals match what the website shows, but for any query of more than one word this is almost always what you want: 'liebherr a 312' goes from 55,623 results to 2. Measured on single words too: 'bagger' 2,463 loose → 117 strict, because strict also matches the word as a whole rather than as a fragment.
category_idoptional1–Browse one category using the source's own numeric id, at ANY level of the tree (8 = construction plant, 105 = excavators, 7 = transport & commercial vehicles, 246 = flatbed/curtain-side trucks, 252 = tractor units, 42 = forklifts & warehouse equipment, 4 = agricultural, 2357 = caravans & motorhomes). Measured to bite at every level: 8 → 9,535, 132 → 645. Get the ids from the `categories` or `suggest` action, or from any `ts-cat-<id>` URL. Combines with `query` and every filter.
category_slugoptional—Browse a category by the source's own URL path instead of by id. This exists because a minority of the child categories the source links are slug-only — its own link carries no numeric id — and `categories` returns `category_id: null` plus this slug for them. Pass it exactly as `categories` returns it ('baumaschinen/gebraucht/grader'). Measured to filter and page identically to an id (645 → 283 used → 26 in Germany). Ignored if `category_id` is also given.
manufactureroptional—Manufacturer, spelled as the source's own facet spells it ('Liebherr', 'Mercedes-Benz', 'MAN', 'Caterpillar', 'DOOSAN' — the case is the source's). Pass a comma-separated list or a JSON array for several; several values widen (OR). Read the available spellings from `facets.manufacturers`. Measured to bite: query=bagger 2,463 → 164 for Liebherr, → 385 for Liebherr or Caterpillar.
machine_typeoptional—The vehicle/machine-type name in that market's language, as printed on the first line of every result ('Mobilbagger', 'Kipper', 'Sattelzugmaschine'). Narrower than `query` because it matches the typed field rather than the whole listing. Measured to bite: 2,463 → 183 for 'Mobilbagger'.
conditionoptionalused · new · ex-display machine · defectiveCondition class. Pass a comma-separated list for several. 🔴 An unknown value is NOT an error on this source — it is dropped and you get the unfiltered catalogue, so this engine validates the value instead of forwarding it ('brandnew' returned the control's own 2,463 rows). Measured to bite: 2,463 → 2,003 used, 380 new.
year_minoptional1900–2100Earliest year of construction, inclusive. 🔴 The source's own field takes a UNIX TIMESTAMP, and a bare year is not rejected — it is MISREAD as a few seconds after 1970, so 'from 2015' silently becomes 'from 1970' (measured: 2,152 results with page-1 years 1980-2022). This engine sends the timestamp the source's own select carries, and the filter then bites exactly: 2,463 → 1,579, every page-1 row 2015-2026.
year_maxoptional1900–2100Latest year of construction, inclusive. Same timestamp conversion as `year_min` — a bare year here is even worse, returning 2 listings instead of 80. Measured: year_max=2000 → 80, every row ≤ 2000; year_min 2015 + year_max 2020 → 797.
operating_hours_minoptional0–Minimum hour-meter reading. This is the machine's HOUR meter, kept separate from `mileage_min` (the odometer) so hours and kilometres are never compared. Measured to bite: 2,463 → 752 above 5,000 h.
operating_hours_maxoptional0–Maximum hour-meter reading. Measured to bite: 2,463 → 517 under 2,000 h.
mileage_minoptional0–Minimum odometer reading in km. A property of road vehicles (trucks, tractor units, vans, buses) and self-propelled plant, separate from the hour meter. Measured to bite: 2,463 → 31 above 100,000 km.
mileage_maxoptional0–Maximum odometer reading in km. Pair it with `mileage_min` for a band: a band is what makes a comparable set, because the odometer is the single biggest price driver on a road vehicle.
price_minoptional0–Minimum price in EUR. Net of VAT unless you also pass `price_band_gross`. Measured to bite: 2,463 → 1,113 for 10,000-50,000 EUR.
price_maxoptional0–Maximum price in EUR. Net of VAT unless `price_band_gross` is also set — on this source a seller may price either way, so a band without that flag is a band on the net figure.
with_price_only = falseoptional—Only listings that publish a price, dropping the 'price on request' ones. Measured to bite: 2,463 → 2,159. Note the inverse is not available: the source ignores `has-price=0` (it returned the full 2,463), so there is no 'price-on-request only' filter to offer. Filter the `price_on_request` field instead.
countryoptional—Seller country as an ISO-3166 alpha-2 code, UPPER CASE ('DE', 'NL', 'AT', 'PL'). Comma-separate for several. 🔴 The source is case sensitive and silently drops a lower-case code — measured: `countries[]=de` answered '0 results' over the unfiltered catalogue — so this engine upper-cases before sending. Measured to bite: 2,463 → 1,457 DE, → 275 NL.
regionoptional—Region/state inside `country`, by the source's OWN NAME, not a code ('Bayern', 'Niedersachsen', 'Nordrhein-Westfalen'). 🔴 A code is silently dropped upstream (`regions[DE][]=BY` answered '0 results' over the unfiltered catalogue). Requires `country`, because the source nests regions under a country. Read the valid names from `facets.regions`; note the source itself publishes both 'Bayern' and 'Bavaria' as separate region values. Measured to bite: country=DE 1,457 → 475 Bayern.
listing_typeoptionalclassified · auction · rentalRestrict to one kind of offer. Measured to bite on query=bagger: classified 2,462, auction 1, rental 47 (and 306 auctions / 1,173 rentals across the whole catalogue). 🔴 Two further flags exist in the source's own form, `is-spare-parts` and `is-buy-now`, and returned ZERO rows for every combination tried (alone, with a keyword, inside a category), so they are not offered rather than offered as filters that always answer nothing.
description_containsoptional—A word that must appear in the seller's free-text description. This searches the prose rather than the typed fields, which is how to find equipment the source has no field for. Measured to bite: 2,463 → 148 for 'hydraulik'.
fuel_typeoptionalgasoline · diesel · electric · gas · hybrid · hydrogenFuel type, by the source's own value. Measured to bite: 2,463 → 581 diesel. 🔴 An unknown value ('petrol') is dropped and answers '0 results' over the unfiltered catalogue, so it is validated here.
emission_classoptionaleuro1 · euro2 · euro3 · euro4 · euro5 · euro6 · euro6b · euro6c · euro6d · euro6d-temp · euro6e · euro7 · noneEuro emission class, by the source's own value. Measured to bite: 2,463 → 23 for euro6.
sort = relevanceoptionalrelevance · price_asc · price_desc · newest · oldest · year_desc · year_asc · updated_desc · updated_asc · manufacturer_asc · manufacturer_desc · machine_type_asc · machine_type_desc · model_asc · model_descResult order. 🔴 Only orders MEASURED to bite are offered: the source accepts an unknown sort field with HTTP 200 and silently falls back to relevance (measured for 'referenz', 'laufzeit', 'einstelldatum' and a nonsense value), and its own dropdown is not the full set of values it honours. `meta.sort_applied` reports the sort the SOURCE says it used, so you never have to trust that the parameter arrived. Sorting by distance is deliberately NOT offered: the source's distance is measured from whoever asks, which for an API is the server, so the same call would order differently from different machines.
Try in playground →
post/truckscout24/v1/suggest1 credit

The source's own autocomplete for a typed prefix, in four buckets: machine/vehicle types, manufacturers, categories (with their numeric id or slug) and products (manufacturer + model pairs). Use it to turn whatever a user typed into values the `machine_type`, `manufacturer`, `model` and `category_id` filters accept, instead of guessing a spelling the source would silently drop.

ParameterAllowed / rangeDescription
queryrequired—What the user has typed so far, at least 2 characters — the source's own autocomplete does not answer a shorter prefix.
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
category_idoptional1–Browse one category using the source's own numeric id, at ANY level of the tree (8 = construction plant, 105 = excavators, 7 = transport & commercial vehicles, 246 = flatbed/curtain-side trucks, 252 = tractor units, 42 = forklifts & warehouse equipment, 4 = agricultural, 2357 = caravans & motorhomes). Measured to bite at every level: 8 → 9,535, 132 → 645. Get the ids from the `categories` or `suggest` action, or from any `ts-cat-<id>` URL. Combines with `query` and every filter.
Try in playground →
post/truckscout24/v1/dealers2 credits

The dealer directory for one category: the dealers themselves, 100 a page, each with company name, street, postcode, town, country, region, trust seal and the dealer id the `seller` action takes. This is the supplier-side view of the marketplace — the source's own figure is over 4,500 dealers. 🔴 The distance it prints beside each dealer, and its own default ordering BY that distance, are both measured from the caller's location and are neither returned nor offered.

ParameterAllowed / rangeDescription
category_idrequired1–The category whose dealers to list. The source's dealer directory is organised per category and has no 'all dealers' page. Use `categories` for the ids.
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
page = 1optional1–Directory page, 100 dealers a page. A page past the last one answers NOT_FOUND; the source publishes no dealer total.
sort = nameoptionalname · postcode · countryDirectory order. 🔴 The source's OWN default order is distance from the viewer, which for an API is the server — the same page would come back in a different order from a different container — so this engine always sends an explicit stable order and does not offer the distance one.
Try in playground →
post/truckscout24/v1/seller2 credits

One dealer's public profile by id: company name, postal address (street, postcode, town, region, country), their own description of the business, the vehicle categories they deal in, the searches the source cross-links from their page, and the trust seal. This is where a listing's seller NAME comes from — the listing page itself keeps it behind a login. 🔴 The listing cards on a dealer's page are login-walled placeholder markup (every one carries the dealer's own name as its title and has listing id 0), so they are deliberately not returned; use `search` for real stock. Contact-person names, phone numbers and e-mail addresses are never returned.

ParameterAllowed / rangeDescription
dealer_idrequired—The dealer's numeric id, as returned by `dealers`, by `search` (each row's `seller_id`) or by `detail` (`listing.seller.dealer_id`). A dealer profile URL containing /tsd/75149/ is accepted too.
market = deoptionalde · at · comWhich TruckScout24 host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 21924313 is EUR 16,900 on all of them — the site does not convert currency). Use 'de' for German wording and 'com' for English. The wider TruckScout24 network has 25 further hosts; only these three have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. One honest caveat: the source's own machine-type translation is unreliable (listing 22233387 is 'LKW mit Pritsche & Plane' on .de and 'Beverage' on .com), which is why 'de' is the default.
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.