How do you get Guazi (瓜子二手车) used-car listings as JSON, in yuan and in dollars?
Call ReefAPI's guazi search action for domestic listings — id, title, year, city, mileage_km, price_cny and the inspection badge come back as JSON — and export_search for the same market priced FOB in US dollars with a condition grade, a seller type and a masked VIN on the detail record. The two things to get right before you store anything: the city you search is a buyer's market and not a location filter, and on the export side an auction row publishes the current bid in the price field, which the engine splits out for you.
This guide demonstrates the real Guazi API engine with a captured response from . The example is only published because the engine passed the SEO snapshot gate.
Chinese used-car pricing, vehicle export sourcing, cross-market arbitrage and residual-value research.
Call the live endpoint
- 1
Treat city as a market, and read each row's own city
The city you pass scopes the buyer's market, not the car's location. Filter on the row's city field if you need one geography.
- 2
Start from brands and series, not a guessed name
The filters take guazi's own slugs. brands returns 327 with their Chinese names; pass one to series for that brand's model-series slugs.
- 3
Narrow instead of paging
Eight hundred rows is the ceiling per facet. Go brand, then series, then price band — a narrow facet returns a small honest result set rather than a padded one.
- 4
Use price_bands rather than inventing a range
Guazi honours its own sixteen bands and silently ignores an arbitrary price filter. The action gives you each band's real yuan range.
- 5
Diff with listing_ids, enrich with detail
Pull ten thousand ids and their last-updated dates for a few credits, compare against your store, and spend detail calls only on what changed.
- 6
On the export side, read price_kind before price
price_usd is an asking price and current_bid_usd is a live bid. Mixing them puts a thirty-dollar opening bid into your market data.
- 7
Do not plan around a VIN domestically
It does not exist on a domestic listing. The export record gives a masked one; otherwise join on the listing id, brand, series, registration month and mileage.
Copy the request
These snippets use the captured request params for guazi/v1/search.
curl -X POST https://api.reefapi.com/guazi/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"city":"bj"}'import requests
r = requests.post(
"https://api.reefapi.com/guazi/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"city": "bj"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/guazi/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"city": "bj"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.guazi.search with {"city":"bj"}.Captured output from ReefAPI
Captured on UTC. The response below is the committed snapshot, including the API envelope and metadata.
{
"method": "POST",
"url": "https://api.reefapi.com/guazi/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"city": "bj"
}
}{
"ok": true,
"meta": {
"api": "guazi",
"endpoint": "search",
"mode": "live",
"latency_ms": 1804.4,
"record_count": 40,
"bytes": 167916,
"cache_hit": false,
"completeness_pct": 0.09,
"stop_reason": "complete",
"result_pool_total": 20439,
"page": 1,
"total_pages": 20,
"max_page": 20,
"rows_per_page": 40,
"facet": {
"city": "bj",
"brand": null,
"series": null,
"price_band": null
},
"city_is_market": true,
"total_results": 43258,
"charged_credits": 1,
"version": "1.0.0",
"request_id": "6ecf22ed82684fee",
"fetched_at": "2026-10-11T12:01:24.953Z"
},
"data": {
"cars": [
{
"id": "c173380464124787",
"clue_id": "173380464124787",
"title": "捷达VS5 2024款 280TSI 手动悦享版",
"year": 2025,
"city": "北京",
"mileage_km": 8400,
"mileage_display": "0.84万公里",
"price_cny": 46900,
"price_display": "4.69万",
"discount_cny": 30000,
"new_car_price_cny": null,
"inspected": true,
"tags": [
"已检测"
],
"thumbnail": "https://image-public.guazistatic.com/qnbdp7206xd200bb4b38694e5683a948e9da4aa5311791545942.jpg?x-bce-process=image/quality,q_88/resize,m_fill,w_280,h_210",
"url": "https://www.guazi.com/car-detail/c173380464124787.html"
},
{
"id": "c173299333296403",
"clue_id": "173299333296403",
"title": "宝骏KiWi EV 2022款 设计师轻享版 磷酸铁锂",
"year": 2022,
"city": "北京",
"mileage_km": 34800,
"mileage_display": "3.48万公里",
"price_cny": 34600,
"price_display": "3.46万",
"discount_cny": 26900,
"new_car_price_cny": null,
"inspected": true,
"tags": [
"已检测",
"纯电动"
],
"thumbnail": "https://image-public.guazistatic.com/qnbdp7206x9d129d3de8f5457fb37e4b9482096d721791354386.jpg?x-bce-process=image/quality,q_88/resize,m_fill,w_280,h_210",
"url": "https://www.guazi.com/car-detail/c173299333296403.html"
},
{
"id": "c169801598214978",
"clue_id": "169801598214978",
"title": "奔驰 Sprinter 2009款 增配版",
"year": 2013,
"city": "北京",
"mileage_km": 99800,
"mileage_display": "9.98万公里",
"price_cny": 68400,
"price_display": "6.84万",
"discount_cny": 30000,
"new_car_price_cny": null,
"inspected": true,
"tags": [
"已检测"
],
"thumbnail": "https://image-public.guazistatic.com/qnbdp7206xf8a3aef42a784d3892f6dcd6558cdee81786368350.jpg?x-bce-process=image/quality,q_88/resize,m_fill,w_280,h_210",
"url": "https://www.guazi.com/car-detail/c169801598214978.html"
}
],
"query": {
"city": "bj",
"brand": null,
"series": null,
"price_band": null,
"page": 1
},
"total_results": 43258,
"result_pool_total": 20439,
"total_pages": 20,
"max_page": 20,
"url": "https://www.guazi.com/bj/"
}
}Why this is hard manually
The city filter does not mean what it looks like. Guazi sells nationwide into each city market, so a page scoped to Beijing legitimately lists cars sitting in Shenyang, and one scoped to Shanghai returned cars from nine separate cities. Scrape it believing you asked for a location and you will build a geographic analysis out of rows that are not geographic, with nothing in the markup to warn you.
The detail page disagrees with itself about the city. The structured data in the page head gave Shenzhen for a car that is in Suzhou — and guazi's own plain-text mirror of the same page says Suzhou. One field is the market you browsed in, the other is where the car is. A scraper that reads the obvious one stores the wrong city on every record.
The unit is a ten-thousand-fold trap. China quotes used cars in 万元 and distance in 万公里, so a listing reading 14.43 and 10.94 means 144,300 yuan and 109,400 kilometres. Take the numbers as they appear and drop them next to a dollar auction feed and everything is wrong by four orders of magnitude. Guazi's own price bands are published the same way: the band labelled 13 to 18 means 130,000 to 180,000 yuan.
There is no VIN on the domestic market, and that is not a wall. The seventeen-character number appears nowhere on a domestic listing under any label, Chinese or English. Guazi's export marketplace does publish one, but masked to the first three and last four characters, with the middle absent from the page entirely. If your pipeline joins vehicles by VIN, the domestic Chinese market cannot be joined that way at all.
The paging stops long before the count does. A city page reports forty-three thousand cars and serves forty a page to page twenty, then nothing — eight hundred rows out of forty-three thousand. The pager does not admit this, and the 'showing 1 to 40 of N' line on the page never changes as you move through the pages, so a scraper that reads it concludes it is still on page one forever.
On the export marketplace the price field means two things. We measured one row publishing thirty dollars for a 2023 Hyundai Palisade with 39,900 km, while the cheapest car on every other facet that minute was between three and thirty-four thousand. It was not a parse error and it was not a thirty-dollar car: the row was a live auction and the field carried the current bid. One field, two meanings, and nothing in its name to tell them apart.
Why ReefAPI solves it
Both marketplaces are one engine, with ten actions. Domestically: search, detail, brands, series, cities, price_bands and listing_ids. On the export side: export_search, export_detail and export_brands. The domestic calls are cheap and the export calls cost more because the source is heavier there; the split is deliberate so that a domestic price sweep does not pay export rates.
The city question is answered rather than hidden. The response flags that the city you passed is a market, and every row carries its own city — the place that car actually is. On the detail record the car's real location comes back as city and the browsing market as market_city, so the contradiction in guazi's own page cannot land in your database as a single wrong value.
Every price and distance is absolute. price_cny is yuan, mileage_km is kilometres, new_car_price_cny is the original list price where guazi shows one, and the price_bands action returns each of the sixteen bands with its real yuan floor and ceiling rather than the 万 figure. Nothing in the payload requires you to know what 万 means.
The condition disclosures are the point. A domestic detail record carries insurance_claim_count, transfer_count, a condition grade, an appearance score out of a hundred and whether an official two-hundred-point inspection report exists. An export record states no-accident, no-flood and no-fire as three separate flags next to an A-to-D grade. Both came back on every car we sampled, and a field guazi does not publish stays null rather than defaulting to something reassuring.
vin is null on the domestic record with a flag saying the source does not publish it. On the export record vin_masked carries exactly what guazi shows — three characters, a mask, four characters — and nothing is reverse-engineered into a full-looking VIN. What you can join on domestically is the listing id, which round-trips unchanged between search and detail, as a string, with its c prefix intact.
The export price is split by meaning. price_usd is an FOB asking price, current_bid_usd is a live auction bid, and price_kind names which one the row carries — so a repricing model cannot read an opening bid as a market value. The export row also carries guazi's own yuan-per-dollar rate, which is what lets you reconcile the two marketplaces instead of guessing at a conversion.
The paging ceiling is published, not discovered. The response reports the page you got, the real maximum and the source's own headline count, and a request for page ninety-nine comes back marked as clamped rather than silently serving page twenty. On the export side the response states outright that no second page is available, because the source's own filter and page links do not work without running its JavaScript — so the engine exposes none of those parameters rather than accepting one it knows will be dropped.
There is a bulk id feed. Guazi publishes a crawler index of every live domestic listing — thirteen pages of roughly ten thousand ids with a last-updated date on each, about 127,000 cars. listing_ids returns a page of that, priced by the rows it returns, which makes a nightly diff affordable: compare dates, then call detail only on what moved. No guazi account, login or token is involved anywhere in the engine.
Questions developers ask
Do I need a Guazi account?
No. Everything the engine reads is public and logged-out. You send a ReefAPI key; there is no guazi login, token or OAuth flow. What guazi puts behind a login is bidding, making an offer and order history — transacting, not data.
Why does my Beijing search contain cars from other cities?
Because guazi sells nationwide into each city market, so the city you pass is the buyer's market rather than the car's location. It is the source's model, not an error, and the response says so. Every row carries its own city, which is where that car actually is.
Can I get the VIN?
Not on the domestic market — the seventeen-character number is not published on a domestic listing under any label, so vin comes back null with a flag saying so. The export marketplace publishes a masked VIN, first three and last four characters, and that arrives as vin_masked. The middle characters are not on the page at all, so nothing more is available from this source.
Is there accident history?
Yes, in two forms. A domestic record carries the number of insurance claims against the car and the number of ownership transfers, plus guazi's condition grade, an appearance score and whether an official two-hundred-point inspection report exists. An export record states no-accident, no-flood and no-fire as explicit flags next to an A-to-D grade.
Why is the price 14.43 instead of something in yuan?
It is not — the engine returns absolute values. China quotes used cars in 万元, ten thousand yuan, so guazi's page shows 14.43; price_cny comes back as 144300. Mileage works the same way, and the price bands are converted too, so the band guazi labels 13 to 18 reports 130,000 to 180,000.
How many cars can I page through?
Eight hundred per facet domestically: forty a page to page twenty, after which the source serves nothing regardless of its own headline count. The export marketplace gives twenty rows per facet and no second page. Reach more by narrowing — brand, then model series, then price band — or by walking the bulk id feed.
What is the difference between search and export_search?
They are two different marketplaces with two different inventories. search reads guazi's domestic Chinese market, priced in yuan, with claim and transfer counts. export_search reads its export and auction platform for overseas buyers — English titles, FOB prices in US dollars, A-to-D grades, damage flags and a masked VIN on the detail record. A car on one is not necessarily on the other.
Can I filter the export market by price or sort it?
No, and the measurement is worth knowing: guazi's own export filter and page links do not work without running its JavaScript — every query-string URL returns a page with no cars on it. So the engine offers brand, series and body style, which are real paths that do work, and offers no price, sort or page parameter it would have to silently ignore.
Can I tell a dealer from a private seller?
Yes, on both marketplaces. Domestically seller_type comes back as dealer or private from guazi's own badge. On the export side it is dealer, private or guazi-owned, which is guazi's own stock rather than a third party's, and the distinction matters because the sourcing guarantee differs.
Is the data in English?
On the export marketplace, yes — guazi writes it in English itself, including the factory options sheet. Domestically no: titles, cities, colours and engine descriptions come back in Chinese as published, with nothing machine-translated. The brand and city directories give you both the Latin slug and the Chinese name.
How do I detect changes without re-pulling everything?
Use listing_ids. Guazi publishes a crawler index of every live domestic listing with a last-updated date on each — about 127,000 cars across thirteen pages of roughly ten thousand. Pull a page, diff the dates against your store, and call detail only on what moved. It is priced by the rows it returns rather than per call.