olx-search
OLX Brazil Search Skill
Search and analyze listings on OLX Brazil (olx.com.br) via CLI.
Prerequisites
# Use the existing venv (already configured)
PYTHON=/home/diogo/dev/olx-search/.venv/bin/python3
# Or install in any venv:
# pip install cloudscraper browser_cookie3
Quick Reference
| Command | Description |
|---|---|
search -q QUERY |
Search listings by keyword |
search -q QUERY -c CATEGORY |
Search within a category |
details --url URL |
Get full details of a listing |
categories |
List all categories |
categories --parent ID |
List subcategories |
cookies |
Extract & verify OLX cookies from browser |
cookies --export FILE |
Export cookies to JSON file |
get-fields -c CATEGORY_ID |
Get required fields for publishing in a category |
publish -t TITLE -d DESC -c CAT -z CEP |
Publish a new ad (requires auth) |
publish ... --dry-run |
Preview publish payload without sending |
list-ads [--status published|deleted] |
List your authenticated OLX ads |
delete --ad-id LIST_ID [--reason ...] |
Delete an ad by listId |
delete ... --dry-run |
Preview delete flow without deleting |
cep CEP |
Look up a Brazilian zipcode |
Script Location
/home/diogo/.agents/skills/olx-search/scripts/olx.py
Commands
1. Search Listings
$PYTHON scripts/olx.py search -q "iphone 15" --limit 5
Arguments:
| Flag | Short | Description | Default |
|---|---|---|---|
--query |
-q |
Search term | (empty = browse) |
--category |
-c |
Category path (friendlyPath) | (all categories) |
--page |
-p |
Page number (1-based) | 1 |
--min-price |
Minimum price in BRL | (none) | |
--max-price |
Maximum price in BRL | (none) | |
--sort |
Sort: price_asc, price_desc, date_desc, date_asc |
relevance | |
--limit |
-l |
Max results to return | 50 (page size) |
Search within a category:
# Search cars
$PYTHON scripts/olx.py search -q "civic 2020" -c "autos-e-pecas/carros-vans-e-utilitarios"
# Search phones with price range
$PYTHON scripts/olx.py search -q "iphone" -c "celulares" --min-price 2000 --max-price 5000
# Browse category without search term
$PYTHON scripts/olx.py search -c "imoveis/aluguel" --max-price 3000
Output structure:
{
"success": true,
"query": "civic 2020",
"total_ads": 645,
"page": 1,
"page_size": 50,
"total_pages": 13,
"results_count": 3,
"related_categories": [
{"name": "Carros", "id": "2020", "count": 600, "url": "/autos-e-pecas/carros?q=civic"}
],
"ads": [
{
"id": 1439467323,
"title": "Civic 2020 Touring 1.5 Turbo",
"price": "R$ 141.990",
"url": "https://df.olx.com.br/...",
"location": "Brasilia - DF",
"location_details": {"city": "Brasilia", "state": "DF", "neighborhood": "Taguatinga"},
"category": "Carros, vans e utilitarios",
"professional_ad": true,
"images": ["https://img.olx.com.br/..."],
"image_count": 6,
"date": 1769523112,
"properties": {
"vehicle_brand": "Honda",
"vehicle_model": "Honda Sedan Touring 1.5 Turbo",
"regdate": "2020",
"mileage": "0",
"fuel": "Gasolina",
"gearbox": "Automatico"
},
"olx_pay": false,
"olx_delivery": false
}
]
}
2. Get Listing Details
$PYTHON scripts/olx.py details --url "https://df.olx.com.br/distrito-federal/carros/civic-2020-1439467323"
Output structure:
{
"success": true,
"url": "https://...",
"id": 1439467323,
"title": "Civic 2020 Touring",
"description": "Full text description...",
"price": "141990",
"currency": "BRL",
"images": ["https://img.olx.com.br/..."],
"seller": "username",
"item_type": "Car",
"metadata": {
"list_id": 1439467323,
"category_id": 2020,
"parent_category_id": 2000,
"city_id": 4530,
"state_id": "61"
}
}
3. Browse Categories
# List all top-level categories
$PYTHON scripts/olx.py categories
# List subcategories of "Autos" (id=2000)
$PYTHON scripts/olx.py categories --parent 2000
# Search categories by name
$PYTHON scripts/olx.py categories -s "celular"
Key category IDs:
| ID | Name | Path |
|---|---|---|
| 1000 | Imoveis | imoveis |
| 2000 | Autos | autos-e-pecas |
| 2020 | Carros | autos-e-pecas/carros-vans-e-utilitarios |
| 3000 | Eletronicos | eletronicos-e-celulares |
| 3060 | Celulares | celulares |
| 4000 | Para a sua casa | para-a-sua-casa |
| 5000 | Esportes e lazer | esportes-e-lazer |
See references/categories.json for the full list of 153 categories.
4. Extract & Verify Cookies
Automatically extracts OLX cookies from the user's browser (Chromium, Chrome, Brave, Firefox, Edge). Cookies are needed for authenticated operations (publishing ads, getting form fields).
# Auto-detect browser and verify authentication
$PYTHON scripts/olx.py cookies
# Use a specific browser
$PYTHON scripts/olx.py cookies --browser brave
# Export cookies to a file
$PYTHON scripts/olx.py cookies --export ~/olx-cookies.json
Output:
{
"success": true,
"browser": "chromium",
"cookie_count": 63,
"authenticated": true,
"user": {
"name": "User Name",
"email": "user@example.com",
"phone": "21999999999",
"zipcode": "01001000",
"verified": true
}
}
Cookie priority chain:
--cookies-file FILE(explicit file path)- Cached cookies (auto-saved from last extraction)
- Auto-extract from browser (tries chromium → chrome → brave → firefox → edge → opera)
Important: The user must be logged in to olx.com.br in their browser for auth cookies to be available.
5. Get Category Fields (for Publishing)
Returns the required and optional fields for publishing an ad in a specific category.
# Get fields for phones (category 3060)
$PYTHON scripts/olx.py get-fields -c 3060
# Get fields for cars (category 2020)
$PYTHON scripts/olx.py get-fields -c 2020
# Use a specific cookies file
$PYTHON scripts/olx.py get-fields -c 3060 --cookies-file ~/olx-cookies.json
Output:
{
"success": true,
"category": "3060",
"field_count": 10,
"fields": [
{
"code": "cellphone_brand",
"param_key": "electronics_brand",
"label": "Marca",
"required": true,
"type": "single_selection",
"datasource_url": "https://ck-gw.olx.com.br/attributes/cellphone_brand/values?format=remote"
}
]
}
6. Publish an Ad
Create a new listing on OLX. Requires authentication (user must be logged in to OLX in their browser).
Workflow: First use get-fields to discover required fields for the category, then publish.
# Step 1: Find the right category
$PYTHON scripts/olx.py categories -s "informatica"
# Step 2: Get required fields for that category
$PYTHON scripts/olx.py get-fields -c 19060
# Step 3: Dry-run to preview the payload
$PYTHON scripts/olx.py publish \
-t "Placa Mae Asus Maximus Hero IX" \
-d "Placa mãe com defeito no soquete. Apenas para retirada de peças." \
-c 19060 \
--price 100 \
-z 01001000 \
--phone-hidden \
--fields '{"info_components_condition": "2", "info_components_type": "10", "exchange": "1"}' \
--dry-run
# Step 4: Publish for real (remove --dry-run)
$PYTHON scripts/olx.py publish \
-t "Placa Mae Asus Maximus Hero IX" \
-d "Placa mãe com defeito no soquete." \
-c 19060 \
--price 100 \
-z 01001000 \
--phone-hidden \
--fields '{"info_components_condition": "2", "info_components_type": "10"}' \
--images photo1.jpg photo2.png
Arguments:
| Flag | Short | Description | Required |
|---|---|---|---|
--title |
-t |
Ad title (max 90 chars) | Yes |
--description |
-d |
Ad description text | Yes |
--category |
-c |
Category ID (numeric) | Yes |
--zipcode |
-z |
CEP (8 digits) | Yes |
--price |
Price in BRL (integer) | No | |
--images |
Image file paths to upload | No | |
--fields |
Category-specific fields as JSON | No | |
--phone-hidden |
Hide phone number | No | |
--condominio |
Condo fee in BRL (real estate) | No | |
--iptu |
IPTU tax in BRL (real estate) | No | |
--dry-run |
Preview payload without publishing | No | |
--browser |
-b |
Browser for cookie extraction | No |
--cookies-file |
Path to cookies JSON file | No |
Success output:
{
"success": true,
"status_code": 200,
"ad_id": 1750090069,
"response": {"ad_id": 1750090069, "show_hv": false},
"request_id": "4e3d6402-b6dc-42c4-9cf8-5f1ba13ed481"
}
Important notes on --fields:
- Fields go FLAT into the API payload (not nested under a key)
- Use
get-fields -c CATEGORY_IDto discover what fields are needed - Each field has a
code(the key to use) andoptions(valid values) - Example:
{"info_components_condition": "2", "exchange": "1"} - Fields can also be passed as a path to a JSON file
Image upload:
- Images are uploaded to
apigw.olx.com.br/ai/imagebefore the ad is created - Supported formats:
.jpg,.jpeg,.png,.webp - The upload response
idis used as"{id}.jpg"in the ad payload
7. List Your Ads
List authenticated user's ads from OLX MyData API.
# List published ads (default)
$PYTHON scripts/olx.py list-ads
# List deleted ads
$PYTHON scripts/olx.py list-ads --status deleted
# Use explicit cookies file
$PYTHON scripts/olx.py list-ads --cookies-file ~/olx-cookies.json
Arguments:
| Flag | Description | Default |
|---|---|---|
--status |
Ad status: published or deleted |
published |
--browser / -b |
Browser for cookie extraction | auto |
--cookies-file |
Path to cookies JSON file | (none) |
Output fields per ad:
listId(ad list id)adId(legacyAdId)titlestatuscategorypricedateurlviews
8. Delete an Ad
Delete one of your ads by listId using the captured 2-step OLX deletion flow.
# Dry-run first (recommended)
$PYTHON scripts/olx.py delete --ad-id 1476080677 --dry-run
# Delete for real
$PYTHON scripts/olx.py delete --ad-id 1476080677 --reason other_reason
# Other reasons
$PYTHON scripts/olx.py delete --ad-id 1476080677 --reason sold_in_olx
$PYTHON scripts/olx.py delete --ad-id 1476080677 --reason sold_elsewhere
$PYTHON scripts/olx.py delete --ad-id 1476080677 --reason gave_up_selling
Arguments:
| Flag | Description | Required |
|---|---|---|
--ad-id |
Ad listId to delete (get from list-ads) |
Yes |
--reason |
Reason: sold_in_olx, sold_elsewhere, gave_up_selling, other_reason |
No |
--dry-run |
Show flow without deleting | No |
--browser / -b |
Browser for cookie extraction | No |
--cookies-file |
Path to cookies JSON file | No |
Flow used:
- Resolve
listId→legacyAdIdvialist-ads/mydata - GET upsell page (
adquirir.olx.com.br/destaques?...) - GET delete completion endpoint (
pos.olx.com.br/complete?...) - Success is validated when response URL contains
deletion-success
9. Look Up CEP (Zipcode)
Validate a Brazilian zipcode and get location data.
$PYTHON scripts/olx.py cep 01001000
$PYTHON scripts/olx.py cep 01001-000
Common Workflows
Price comparison
# Search, then compare prices for same product across sellers
$PYTHON scripts/olx.py search -q "macbook pro m3" --sort price_asc --limit 10
Market analysis
# Get all listings in a category for a region
$PYTHON scripts/olx.py search -c "imoveis/aluguel" --min-price 1000 --max-price 3000 --limit 50
Listing investigation
# First search, then get details on interesting listings
$PYTHON scripts/olx.py search -q "mesa escritorio" --limit 5
# Then get details on a specific ad
$PYTHON scripts/olx.py details --url "https://..."
Publish an ad (full workflow)
# 1. Find category ID
$PYTHON scripts/olx.py categories -s "celular"
# 2. Get required fields for that category
$PYTHON scripts/olx.py get-fields -c 3060
# 3. Validate your CEP
$PYTHON scripts/olx.py cep 01001000
# 4. Dry-run to check payload
$PYTHON scripts/olx.py publish -t "iPhone 14" -d "iPhone 14 128GB" -c 3060 -z 01001000 --price 3500 --fields '{"cellphone_brand": "2"}' --dry-run
# 5. Publish for real
$PYTHON scripts/olx.py publish -t "iPhone 14" -d "iPhone 14 128GB" -c 3060 -z 01001000 --price 3500 --fields '{"cellphone_brand": "2"}' --images iphone.jpg
Technical Notes
- Each search page returns up to 50 results
- Use
--page Nfor pagination (page 2, 3, etc.) - The
datefield in ads is a Unix timestamp - Properties vary by category (cars have vehicle-specific fields, phones have storage/brand, etc.)
- Rate limit: add a few seconds delay between requests to avoid blocking
- Cloudflare is bypassed automatically via cloudscraper
- Cookies are auto-extracted from the user's browser via
browser_cookie3 - Extracted cookies are cached at
~/.agents/skills/olx-search/.cookies_cache.json - Commands that need auth (
get-fields,publish) auto-extract cookies if no--cookies-fileis given - Commands that need auth (
get-fields,publish,list-ads,delete) auto-extract cookies if no--cookies-fileis given search,details,categories, andcepdo NOT require authenticationpublishuses the real OLX ad insertion API (POST /ai-bff/v2/anuncio/)list-adsusesGET /mydata/v1/datawith OLX team key and account origin headersdeleteuses the 2-step flow:adquirir.olx.com.br/destaquesthenpos.olx.com.br/complete- Image upload uses
POST /ai/imagewith multipart form data - The publish payload format was reverse-engineered from a real successful publish (verified HTTP 200)
Error Handling
Errors return JSON with an error field:
{"error": "Failed to fetch page (HTTP 403)", "url": "..."}
Exit code 1 on errors, 0 on success.