How to scrape automotive data from Kavak using the Minexa API
- Minexa.ai

- Jul 7
- 5 min read
Kavak is one of Latin America's largest used car marketplaces, and its Brazilian listings page at kavak.com/br/seminovos contains hundreds of vehicle cards updated regularly with price, mileage, model year, location, and direct links to individual detail pages. Extracting that data at scale without writing custom scraper code is exactly what the Minexa API is built for.
This walkthrough covers the full workflow: training a scraper once using the Minexa Chrome extension, then calling the Minexa API programmatically to pull structured vehicle data across as many pages as you need.
Watch the full tutorial first
The video below walks through every step shown in this guide. Watch it before going through the screenshots so the sequence makes sense end to end.
What the extracted data looks like
Before going through the steps, here is a sample of what the Minexa API returns for two Kavak listings. Fields prefixed with meta__ are internal tracking fields and are excluded below for clarity.
[
{
"vehicle_brand_model": "Chevrolet - Onix",
"vehicle_model": "1.0 FLEX MANUAL",
"location": "Canoas - RS",
"mileage": "68.673km",
"model_year": "2024/2024",
"price": "R$ 59.900",
"vehicle_page_url": "https://www.kavak.com/br/...",
"item_description": ""
},
{
"vehicle_brand_model": "Hyundai - Hb20",
"vehicle_model": "1.0 12V FLEX SENSE PLUS MANUAL",
"location": "Porto Alegre - RS",
"mileage": "60.072km",
"model_year": "2023/2024",
"price": "R$ 64.540",
"vehicle_page_url": "https://www.kavak.com/br/...",
"item_description": ""
}
]
Each row maps to one vehicle card on the Kavak listings page. The vehicle_listing field, covered further below, contains a richer nested array with additional attributes per card.
Step 1: Open Kavak and confirm the page
Navigate to kavak.com/br/seminovos in Chrome. Once the page has loaded and the vehicle cards are visible, open the Minexa extension from your browser toolbar.
The extension detects the current page automatically. Click the confirmation button to tell Minexa you are on the correct page and ready to proceed.
Step 2: Review pagination and choose scraping scope
Minexa detects the pagination controls on the Kavak listings page and shows you what it found. Review the detected next-page logic, then click Continue.
Next, choose whether to scrape the listing cards only, or to also follow each card's link and extract data from the individual vehicle detail pages. For most pricing and inventory monitoring use cases, list-only is sufficient. If you need full vehicle specs or inspection data, choose list plus detail pages.
Step 3: Select scraping mode and highlight the container
Choose between simple and advanced scraping mode. Simple mode works for most Kavak pages. Advanced mode lets you define custom JavaScript interactions before extraction runs, which is useful if the page requires a scroll or a filter interaction to surface all cards.
After selecting a mode, Minexa highlights the full container wrapping all the vehicle listing cards. You are not clicking individual fields here. You are selecting the parent element that holds the entire list, and Minexa discovers all the data points within it automatically.
Step 4: Review extracted columns and get the API request
Once the scraper is created, Minexa displays all the data columns it identified. Use the navigation arrows to scroll through the full list of extracted fields. Key columns for Kavak include vehicle_brand_model, vehicle_model, location, mileage, model_year, price, vehicle_page_url, vehicle_image_url, item_description, and vehicle_listing.
Click API Request in the top right. Minexa generates ready-to-run Python code with your scraper_id pre-filled. Copy it directly from the extension.
Understanding the vehicle_listing field
The vehicle_listing field returns a structured array of typed objects per card. Each object includes a tag, type, attribute, and value. A single card's array encodes the full detail page href, the brand and model display text as separate span elements, the trim level string, the city and state location, the odometer reading, the model year range, the asking price, a CSS class string identifying the card's promotion tier (for example destaque super), a promotional label text, a WhatsApp contact button class attribute, and a consultant contact label.
In Python, extracting all values from this field is straightforward:
values = [item["value"] for item in row["vehicle_listing"]]
The item_description field is worth noting separately. It only appears as a non-empty value on select cards that carry an inventory classification badge such as Quase novo. On all other cards it returns an empty string. This makes it directly usable as a filter condition when segmenting inventory by classification tier without any post-processing.
Running extraction via the API
Once the scraper is trained and you have your scraper_id, all future extractions run through the Minexa API without touching the extension again. Pass your list of Kavak listing page URLs in the request body. Pagination across multiple pages must be handled by defining the appropriate JavaScript interaction in your scraping scenario. The API does not auto-paginate on your behalf.
The Python script below handles paginated API responses, writes a checkpoint file after each batch, and saves output as JSON, CSV, and Excel at every iteration so no data is lost if a run is interrupted.
import pandas as pd
import json, os, requests
from datetime import datetime
url = "https://api.minexa.ai/data/"
api_key = "YOUR_API_KEY"
data = {
"batches": [{
"scraper_id": 6341,
"columns": ["top_30"],
"urls": ["https://www.kavak.com/br/seminovos"],
"scraping": {
"js_render": True,
"timeout": 30,
"js_code": [{"wait_time": 2}, {"page_init": True}, {"wait_time": 4}],
"proxy": "verified",
"retry": 3
}
}],
"threads": 3
}
headers = {"Content-Type": "application/json", "api-key": api_key}
next_set, started = None, False
iterated_data, extracted_data = [], []
file_path = f"kavak_{datetime.now():%Y_%m_%d_%H_%M}"
while not started or next_set:
if next_set:
data["next"] = next_set
response = requests.post(url, json=data, headers=headers)
j = response.json()
started = True
for extraction in j["response"]:
for row in extraction["results"]:
if row.get("error"): continue
iterated_data.append({
k: v if isinstance(v, str) else [x["value"] for x in v]
for k, v in row.items()
})
extracted_data += j["response"]
with open(f"{file_path}.json", "w") as f:
json.dump(extracted_data, f, indent=2)
pd.DataFrame(iterated_data).to_excel(f"{file_path}.xlsx", index=False)
next_set = j.get("meta", {}).get("next")
if not next_set: break
Replace scraper_id with the value generated by your extension session, and update the urls list with the Kavak pages you want to process. The columns value top_30 returns the top thirty ranked fields. You can switch this to a named list of specific columns if you only need a subset.
If Kavak's page requires heavier JavaScript rendering or triggers anti-bot checks, switch to a more capable scraping provider in the scraping object. The extension's API Request dropdown lets you select pre-built scenarios ranked by capability and credit cost, which is the fastest way to find the right configuration for a given site.
Ready to get started? Install the Minexa Chrome extension and train your first Kavak scraper in a few minutes. The scraper_id it generates is all you need to run extractions at any scale from that point forward.
For a closer look at how the API request is structured and what each parameter controls, see: How to scrape jobs data from Apna using the Minexa.ai API.

Comments