Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the PakWheels API page →
Classifieds & Second-hand

PakWheels API & Scraper

PakWheels is where vehicles are bought and sold in Pakistan, and this API turns its three marketplaces into JSON.

7 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.

Searching cars returns 25 ads a page out of 83,787, each with the make, model and trim, the model year, the asking price as an exact rupee figure, the odometer in kilometres, fuel, engine size, gearbox, the city, the photo, the photo count, whether the seller paid to feature the ad and when it was last bumped. The bike surface works the same way over 21,573 motorcycles and scooters, and the parts surface over 58,934 accessory and spare-part listings with the site's own two-level category path. Give an ad id back to the detail endpoint and you get the whole page: the seller's own comments, the complete feature list, every photo, the exterior colour, the city the vehicle is registered in, assembly, the ad reference and the seller's public profile. Prices are the honest part. PakWheels writes them in local scale on the page, so the same car reads 'PKR 2.07 crore' in the list and 'PKR 207.0 lacs' on its own ad, and we return the exact integer 20700000 next to the site's own string so your numbers never pick up a hundred-fold error. On 375 rows across the three marketplaces the integer and the printed string agreed 375 times and disagreed none. Twenty filters are offered and all twenty were measured to move the result count, which is why the city filter is missing from the parts endpoint: the site accepts it there and quietly ignores it.

Reference

What a PakWheels search row carries

Measured on 2026-10-02 over 250 car rows from ten different queries, 75 bike rows and 50 parts rows. The three columns that are not 100 % are real gaps in the source, not parser misses.

FieldWhat it isFilled
ad_idNumeric PakWheels ad id; feed it straight back to the detail endpoint100 %
price_pkrAsking price as an exact whole-rupee integer242/250 cars, 75/75 bikes, 50/50 parts
price_displayThe price string PakWheels itself prints ('PKR 2.07 crore')100 %
price_before_discount_pkrThe struck-through old price, when the ad shows oneonly on discounted ads
brand / model / variantMake, model and trim as the site tags them100 % / 100 % / 237/250
year / mileage_kmModel year and odometer in kilometres100 % / 100 %
fuel / engine_cc / transmissionPetrol, diesel, hybrid, electric, PHEV; engine size; gearbox (cars)100 % / 247/250 / 100 %
engine_typeBikes only: '4 Stroke', '2 Stroke' or 'Electric'75/75 bikes
cityThe city the ad is posted in100 % cars and bikes
category / sub_categoryParts only: the site's own two-level category path50/50 parts
featuredWhether the seller paid to feature this adalways present
image_url / images_countLead photo and how many photos the ad has100 %
updated_textWhen the ad was last bumped, as the site words it100 % cars and bikes

Eight of 250 car ads carry no price at all; those come back with price_pkr: null and price_on_request: true rather than a zero. A page holds 25 rows on the car and bike surfaces and 24 on the parts surface, and every response repeats page_size, pages and the window the site says it served, so you never have to assume.

Live example

Real request and response JSON

Captured from the indexed primary action, car_search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/pakwheels/v1/car_search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "make": "toyota",
    "city": "lahore",
    "max_results": 20
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "pakwheels",
    "endpoint": "car_search",
    "mode": "live",
    "latency_ms": 1700.5,
    "record_count": 25,
    "bytes": 580175,
    "cache_hit": false,
    "price_witness": {
      "match": 25,
      "mismatch": 0,
      "unreadable_display": 0
    },
    "schema_rows_on_page": 25,
    "featured_rows": 4,
    "charged_credits": 1,
    "version": "0.1.0",
    "request_id": "7f619251988346df",
    "queue_ms": 1.2
  },
  "data": {
    "total_results": 2538,
    "page": 1,
    "page_size": 25,
    "pages": 102,
    "reachable_results": 2538,
    "page_window": "1 - 25",
    "has_more": true,
    "count": 25,
    "duplicates_dropped": 0,
    "filters_applied": {
      "make": "toyota",
      "city": "lahore",
      "sort": "bumped_at-desc",
      "page": 1
    },
    "search_url": "https://www.pakwheels.com/used-cars/search/-/mk_toyota/rg_lahore/?sortby=bumped_at-desc",
    "cars": [
      {
        "ad_id": "12076090",
        "url": "https://www.pakwheels.com/used-cars/toyota-vitz-2008-for-sale-in-peshawar-12076090",
        "title": "Toyota Vitz 2008 F 1.3",
        "price_pkr": 2265000,
        "price_currency": "PKR",
        "price_display": "PKR 22.65 lacs",
        "price_before_discount_pkr": null,
        "price_before_discount_display": null,
        "price_on_request": false,
        "image_url": "https://cache4.pakwheels.com/ad_pictures/1526/toyota-vitz-1-3-f-2008-152618674.webp",
        "images_count": 9,
        "featured": false,
        "city": "Peshawar",
        "brand": "Toyota",
        "model": "Vitz",
        "managed_by_pakwheels": false,
        "updated_text": "Updated about 2 hours ago",
        "availability": "InStock",
        "variant": "F 1.3",
        "year": 2008,
        "mileage_km": 109809,
        "fuel": "Petrol",
        "engine_cc": 1300,
        "transmission": "Automatic"
      },
      {
        "ad_id": "12062014",
        "url": "https://www.pakwheels.com/used-cars/toyota-corolla-2009-for-sale-in-lahore-12062014",
        "title": "Toyota Corolla 2009 Altis Cruisetronic 1.8",
        "price_pkr": 2950000,
        "price_currency": "PKR",
        "price_display": "PKR 29.5 lacs",
        "price_before_discount_pkr": null,
        "price_before_discount_display": null,
        "price_on_request": false,
        "image_url": "https://cache3.pakwheels.com/ad_pictures/1524/toyota-corolla-1-8-cruisetronic-2009-152408733.webp",
        "images_count": 12,
        "featured": true,
        "city": "Lahore",
        "brand": "Toyota",
        "model": "Corolla",
        "managed_by_pakwheels": false,
        "updated_text": "Updated about 2 hours ago",
        "availability": "InStock",
        "variant": "Altis Cruisetronic 1.8",
        "year": 2009,
        "mileage_km": 131452,
        "fuel": "Petrol",
        "engine_cc": 1800,
        "transmission": "Automatic"
      },
      {
        "ad_id": "12076004",
        "url": "https://www.pakwheels.com/used-cars/toyota-prius-2017-for-sale-in-lahore-12076004",
        "title": "Toyota Prius 2017 S Safety Plus II",
        "price_pkr": 6295000,
        "price_currency": "PKR",
        "price_display": "PKR 62.95 lacs",
        "price_before_discount_pkr": null,
        "price_before_discount_display": null,
        "price_on_request": false,
        "image_url": "https://cache3.pakwheels.com/ad_pictures/1526/toyota-prius-s-safety-plus-ii-2017-152617445.webp",
        "images_count": 5,
        "featured": true,
        "city": "Lahore",
        "brand": "Toyota",
        "model": "Prius",
        "managed_by_pakwheels": false,
        "updated_text": "Updated about 4 hours ago",
        "availability": "InStock",
        "variant": "S Safety Plus II",
        "year": 2017,
        "mileage_km": 103050,
        "fuel": "Hybrid",
        "engine_cc": 1800,
        "transmission": "Automatic"
      }
    ]
  }
}
Actions

What the PakWheels API does

ActionDescriptionConcrete use caseKey params
car_searchSearch the live Pakistani used-car market on pakwheels.com. Every row is one ad: make, model, variant, model year, asking price in exact PKR rupees plus the site's own printed string ('PKR 2.07 crore'), odometer in km, fuel, engine size, transmission, city, photo, photo count, whether the seller paid to feature it, whether PakWheels manages the sale, and when it was last bumped. total_results is the site's own count, and page_size, pages and page_window come from the response rather than from a constant. Every filter offered here was measured to move that total in the same run; filters the source accepts and ignores are deliberately absent. Call with no parameters to page the whole market.Price-intelligence teams call car_search to search the live Pakistani used-car market on pakwheels.com.query, make, model, city, province, ...
car_listingThe FULL ad behind a car ad_id: everything the detail page publishes. Adds what a search row cannot carry — the seller's own free-text comments, the complete feature list, every photo at slide size, exterior colour, body type, assembly, the city the car is registered in, the ad reference number, the last-updated date, the site's own label/value spec table verbatim, and the seller block (display name, member-since date, profile image). The one field this surface does NOT publish is the phone number: the page prints a mask and the real number sits behind a click, so no fake field is returned. A dead id answers NOT_FOUND, never an empty success.Classifieds aggregators call car_listing to get the FULL ad behind a car ad_id.ad_id
bike_searchSearch the live Pakistani used-motorcycle and scooter market. Same row shape as the car search where the source publishes the same facts: make, model, year, exact PKR price plus the printed string, odometer, engine type, city, photo, featured flag and bump time. 🔴 This surface is NOT the car surface with a different path — it was measured separately: bike result rows carry no embedded product schema (0 blocks for 25 rows, against 25+ on the car surface), so the row data is read from the row markup and the engine-size, body type, colour and assembly filters the car surface offers are not offered here because they are not part of this surface's own facet set. Measured market size 21,573 bikes.Resale and arbitrage tools call bike_search to search the live Pakistani used-motorcycle and scooter market.query, make, model, city, province, ...
bike_listingThe FULL ad behind a bike ad_id: the seller's comments, the bike-feature list (disc brake, LED light…), every photo, colour, registered-in city, assembly, body type, engine type, the ad reference, the last-updated date, the site's own spec table verbatim and the seller block. A dead id answers NOT_FOUND.Lead-generation teams call bike_listing to get the FULL ad behind a bike ad_id.ad_id
part_searchSearch PakWheels' auto-parts and accessories marketplace: 58,934 live listings measured on 2026-10-02. Every row is one part: title, exact PKR price, the site's own two-level category path (for example 'Engine & Mechanical' → 'Car Clutch Plate'), photo, photo count and whether it is available for instant Buy Now checkout. 🔴 Only the keyword filter is offered on this surface, and that is a measurement, not an omission: the city filter that bites on cars and bikes is accepted with HTTP 200 and silently ignored here (58,934 → 58,934, byte-identical), so it is not exposed. Keyword does bite: 58,934 → 661 for 'clutch'. Pages hold 24 rows on this surface, not 25.Price-intelligence teams call part_search to search PakWheels' auto-parts and accessories marketplace.query, sort, page
part_listingThe full parts/accessory ad behind an ad_id: the seller's own description, the stock keeping id the site assigns, the brand, every photo and the site's own spec table. A dead id answers NOT_FOUND.Classifieds aggregators call part_listing to get the full parts/accessory ad behind an ad_id.ad_id
filter_optionsThe filter vocabulary this API accepts, group by group, with the label PakWheels itself prints next to each value and the measured ad count behind the ones that were counted. Read this before building a filter UI. It is served from the vocabulary the engine validates against, so it costs no upstream request and can never drift away from what the API will accept. Make, model and city are deliberately NOT enumerated here: PakWheels lists hundreds of each and they are open text tokens in its own urls.Resale and arbitrage tools call filter_options to get the filter vocabulary this API accepts, group by group, with the label PakWheels itself print….none
Code samples

Call car_search from your stack

curl -X POST https://api.reefapi.com/pakwheels/v1/car_search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"make":"toyota","city":"lahore","max_results":20}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.pakwheels.car_search with {"make":"toyota","city":"lahore","max_results":20}.
Use cases

Who uses this API and why

  • Price a car against the live Pakistani market: filter by make, model, year band and city, read the exact PKR figures and build your own distribution instead of trusting a dealer's quote.
  • Watch a model for arrivals: poll Toyota Corolla in Lahore sorted by newest, keep the ad ids you have seen and alert on the ones you have not.
  • Separate dealer stock from private sellers: seller_kind splits the 83,787-ad market into 73,130 private and 10,658 dealer ads, which is the difference between a retail benchmark and a trade one.
  • Build an import-vs-local view: the assembly filter splits 60,912 locally assembled cars from 22,872 imports, and the origin filter groups them by Japanese, German, Korean, Chinese and more.
  • Track spare-part pricing: search the 58,934-listing parts marketplace by keyword, read the category path and the Buy-Now flag, and follow a part's price and its struck-through old price over time.
FAQ

Questions developers ask before integrating

How many listings can I actually reach?

All of them. The unfiltered car market measured 83,787 ads over 3,352 pages, and page 3,352 really does serve the last 10 ads (3,351 x 25 + 10 = 83,785 on the run we checked). Asking for a page past the end gets you a clear NOT_FOUND with the page count, not the last page dressed up as page 4,800. Every response states reachable_results alongside total_results.

Prices on PakWheels are written in lacs and crore. What do I get?

An exact integer in rupees, plus the site's own string. A car listed as 'PKR 2.07 crore' comes back as price_pkr: 20700000 and price_display: 'PKR 2.07 crore'. We check the two against each other on every row and report the tally: 375 rows checked on 2026-10-02, 375 agreed, 0 disagreed. If an ad shows a discount we also return the struck-through old price in its own field, so the live price and the old price never get mixed up.

Can I filter to dealers only, or to private sellers only?

Yes, with seller_kind. On 2026-10-02 the market split 73,130 ads from individuals and 10,658 from dealers. Every detail response also carries the seller block: display name, the date they joined PakWheels and their profile image.

Does the API return seller phone numbers?

No, and that is deliberate. The public ad page prints a masked number and the real one only appears after a click, so there is no phone number on the surface we read. We would rather return no field than a field that is the same fake string on every ad. The seller's display name and member-since date are returned.

Do the filters really narrow the results, or are some ignored?

All twenty filters we expose were measured against the unfiltered total in the same run: city 83,787 -> 11,441 for Lahore, make 83,787 -> 22,879 for Toyota, make+model -> 9,993 for Toyota Corolla, automatic -> 48,228, imported -> 22,872, PakWheels-inspected -> 2,688, with video -> 186. The one filter that does not narrow anything is not offered: the city filter is accepted on the parts marketplace and silently ignored there (58,934 before, 58,934 after), so part_search takes keyword, sort and page only.

Are bikes and spare parts the same endpoint as cars?

No, they are separate endpoints because they are genuinely different pages. The bike marketplace publishes no engine size, no gearbox and no stock status on its search rows, so those fields are absent from a bike row instead of returned empty; what it does publish is the engine class, and that is filled on 75 of 75 rows we measured. The parts marketplace publishes no city, no make and no bump time on its rows, and holds 24 rows a page instead of 25.

What happens with a dead or deleted ad id?

NOT_FOUND, not an empty success. PakWheels answers a real 404 for an id that does not exist, and we pass that through. A detail page also shows five similar ads with their own prices, so we match the schema block to the id you asked for and refuse rather than hand you a neighbour's car.

Which filter values are valid?

Call filter_options. It costs nothing and no request, and returns every enum we accept with the label PakWheels itself prints next to it: 20 body types, 7 fuels, 23 colours, 9 origin groups, 8 provinces, 8 sort orders. Make, model and city are open text in the site's own url spelling ('toyota', 'corolla', 'lahore'), so they are listed as open fields rather than invented into a closed list.

What is the PakWheels API?

PakWheels API is a ReefAPI endpoint group for pakistan's car, bike and auto-parts marketplace It returns live JSON through POST requests under /pakwheels/v1.

Is the PakWheels API free to try?

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

Do I need a PakWheels login or account?

No login to PakWheels 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 PakWheels data?

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

How many credits does the PakWheels API use?

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

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

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

docs / pakwheels

PakWheels

Pakistan's car, bike and auto-parts marketplace

base /pakwheels/v17 endpoints
post/pakwheels/v1/car_listing3 credits

The FULL ad behind a car ad_id: everything the detail page publishes. Adds what a search row cannot carry — the seller's own free-text comments, the complete feature list, every photo at slide size, exterior colour, body type, assembly, the city the car is registered in, the ad reference number, the last-updated date, the site's own label/value spec table verbatim, and the seller block (display name, member-since date, profile image). The one field this surface does NOT publish is the phone number: the page prints a mask and the real number sits behind a click, so no fake field is returned. A dead id answers NOT_FOUND, never an empty success.

ParameterAllowed / rangeDescription
ad_idrequired—The numeric ad id exactly as a search row returns it in ad_id. The slug is not needed: /used-cars/<id> redirects to the canonical url (measured). A removed or non-existent id answers a real HTTP 404 upstream and becomes NOT_FOUND.
Try in playground →
post/pakwheels/v1/bike_listing2 credits

The FULL ad behind a bike ad_id: the seller's comments, the bike-feature list (disc brake, LED light…), every photo, colour, registered-in city, assembly, body type, engine type, the ad reference, the last-updated date, the site's own spec table verbatim and the seller block. A dead id answers NOT_FOUND.

ParameterAllowed / rangeDescription
ad_idrequired—The numeric ad id exactly as a search row returns it in ad_id. The slug is not needed: /used-cars/<id> redirects to the canonical url (measured). A removed or non-existent id answers a real HTTP 404 upstream and becomes NOT_FOUND.
Try in playground →
post/pakwheels/v1/part_listing3 credits

The full parts/accessory ad behind an ad_id: the seller's own description, the stock keeping id the site assigns, the brand, every photo and the site's own spec table. A dead id answers NOT_FOUND.

ParameterAllowed / rangeDescription
ad_idrequired—The numeric ad id exactly as a search row returns it in ad_id. The slug is not needed: /used-cars/<id> redirects to the canonical url (measured). A removed or non-existent id answers a real HTTP 404 upstream and becomes NOT_FOUND.
Try in playground →
post/pakwheels/v1/filter_options1 credit

The filter vocabulary this API accepts, group by group, with the label PakWheels itself prints next to each value and the measured ad count behind the ones that were counted. Read this before building a filter UI. It is served from the vocabulary the engine validates against, so it costs no upstream request and can never drift away from what the API will accept. Make, model and city are deliberately NOT enumerated here: PakWheels lists hundreds of each and they are open text tokens in its own urls.

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.