Install
openclaw skills install divar-apiUse this skill whenever the user wants to search, query, or extract data from Divar (divar.ir) — Iran's largest classifieds platform. Triggers include: searching rental or sale listings, filtering by district/price/size/rooms/amenities, paginating through results, fetching post details, getting contact info, building any kind of Divar search tool or scraper, or any question about the Divar API structure. Also use when the user pastes a divar.ir URL and wants to replicate or automate that search. Always use this skill when Divar, divar.ir, or Iranian real-estate search is mentioned.
openclaw skills install divar-apiDivar uses a server-driven widget API (JSON over HTTPS, protobuf type annotations embedded via @type).
All responses are lists of typed widget_type objects. Base URL: https://api.divar.ir.
Every filter field uses a typed wrapper. Wrong type = HTTP 400. Use this table exactly:
| Field | Wrapper | Example |
|---|---|---|
category | str | { "str": { "value": "residential-rent" } } |
sort | str | { "str": { "value": "sort_date" } } |
districts | repeated_string | { "repeated_string": { "value": ["920", "82"] } } |
rooms | repeated_string | { "repeated_string": { "value": ["یک", "دو"] } } |
rent | number_range | { "number_range": { "minimum": "20000000", "maximum": "60000000" } } |
credit | number_range | { "number_range": { "minimum": "300000000", "maximum": "600000000" } } |
size | number_range | { "number_range": { "minimum": "80", "maximum": "120" } } |
balcony | boolean | { "boolean": { "value": true } } |
parking | boolean | { "boolean": { "value": true } } |
number_rangemin/max values are strings, not numbers.booleanvalue is a JS boolean (true/false), not a string.
The API slug differs from the divar.ir URL path segment. Never use the URL segment as the slug.
API slug (category.str.value) | URL path | Persian |
|---|---|---|
residential-rent | rent-residential | اجاره مسکونی |
apartment-sell | apartment-sell | فروش آپارتمان |
apartment-rent | rent-apartment | اجاره آپارتمان |
buy-residential | buy-residential | فروش مسکونی |
real-estate | real-estate | همه ملک |
buy-commercial-property | buy-commercial-property | فروش اداری/تجاری |
rent-commercial-property | rent-commercial-property | اجاره اداری/تجاری |
rent-temporary | rent-temporary | اجاره کوتاهمدت |
When in doubt, intercept a real browser request via DevTools to read the actual category.str.value.
POST /v8/postlist/w/search
Verified working payload (residential rental, Tehran, tested 2026-04-01 → returned 24 listings):
{
"city_ids": ["1"],
"source_view": "SEARCH",
"disable_recommendation": false,
"search_data": {
"form_data": {
"data": {
"category": { "str": { "value": "residential-rent" } },
"districts": { "repeated_string": { "value": ["139","143","145","4162","75","78","82","920","921"] } },
"rooms": { "repeated_string": { "value": ["دو","یک"] } },
"rent": { "number_range": { "minimum": "20000000", "maximum": "60000000" } },
"credit": { "number_range": { "minimum": "300000000", "maximum": "600000000" } },
"size": { "number_range": { "minimum": "80", "maximum": "120" } },
"balcony": { "boolean": { "value": true } },
"parking": { "boolean": { "value": true } }
}
},
"server_payload": {
"@type": "type.googleapis.com/widgets.SearchData.ServerPayload",
"additional_form_data": {
"data": { "sort": { "str": { "value": "sort_date" } } }
}
}
}
}
Response: { "list_top_widgets": [...], "list_widgets": [...] }
Filter to widget_type === "POST_ROW" to get listings. Each POST_ROW has:
data.title — listing title (Persian)data.middle_description_text — price stringdata.bottom_description_text — relative time ("دقایقی پیش")data.action.payload.token — unique post ID (use for detail/contact endpoints)data.action.payload.web_info.district_persian — district namedata.image_count — number of photosCursor-based. On page 1, no pagination_data. On page 2+, add:
{
"pagination_data": {
"@type": "type.googleapis.com/post_list.PaginationData",
"last_post_date": "<ISO8601 from previous last post>",
"page": 2,
"layer_page": 2,
"search_uid": "<uuid — keep constant for the session>",
"cumulative_widgets_count": 24
}
}
viewed_tokens is an optional gzip+base64 bloom filter for server-side deduplication — safe to omit.
GET /v8/posts-v2/web/{token}
Returns sections (BREADCRUMB, HEADER, IMAGES, DETAILS) each containing widget arrays.
Common detail widget types: KEY_VALUE (room count, floor, etc.), DESCRIPTION, IMAGE_GALLERY, MAP.
POST /v8/postcontact/web/contact_info_v2/{token}
Body: {}. Returns widget_list with UNEXPANDABLE_ROW containing phone number.
Returns RBAC: access denied without authentication.
token cookie + did (device ID) cookie, set by divar.ir on login.Authorization: Basic <jwt> — same JWT value as the token cookie.divar.ir.Authorization header explicitly.When a user pastes a URL like:
https://divar.ir/s/tehran/rent-residential/almahdi?balcony=true&credit=300000000-600000000&districts=920%2C82&rent=20000000-60000000&rooms=%D8%AF%D9%88%2C%DB%8C%DA%A9&size=80-120
Map query params to form_data fields:
| URL param | form_data field | Wrapper |
|---|---|---|
URL path segment (e.g. rent-residential) | category → look up API slug | str |
districts=920,82,... | districts | repeated_string (split on ,) |
rooms=دو,یک | rooms | repeated_string (split on ,) |
rent=min-max | rent | number_range (split on -) |
credit=min-max | credit | number_range (split on -) |
size=min-max | size | number_range (split on -) |
balcony=true | balcony | boolean |
parking=true | parking | boolean |
map_bbox=... | not in form_data — belongs in /v8/mapview/viewport camera_info.bbox | — |
map_place_hash=... | not in form_data | — |
For full API reference (all endpoints, widget system, map/geo, autocomplete, filters):
→ read references/api-reference.md