Realtor.com Agent Directory
US real estate agent profiles by ZIP code — brokerage, licences, contact details and transaction volume.
0 rows in the dataset
Download the dataset
Get every row this scraper has collected as one CSV or JSONL file. If the data is older than maxAgeHours, the scraper is re-run with its configured settings first. The key needs the datasets:export scope.
DOWNLOAD_ID=$(curl -s -X POST "https://api.pandorlabs.com/v1/datasets/realtor-agents/downloads" \ -H "Authorization: Bearer $PANDORLABS_KEY" \ -H "Content-Type: application/json" \ -d '{"maxAgeHours":24,"format":"csv"}' | jq -r '.id')while true; do STATUS=$(curl -s "https://api.pandorlabs.com/v1/downloads/$DOWNLOAD_ID" \ -H "Authorization: Bearer $PANDORLABS_KEY" | jq -r '.status') [ "$STATUS" != "refreshing" ] && break sleep 5donecurl -s "https://api.pandorlabs.com/v1/downloads/$DOWNLOAD_ID/file" \ -H "Authorization: Bearer $PANDORLABS_KEY" \ -o dataset.csvThe rate is 1 credit per 100 rows cached and 2 credits live, charged on the rows in the dataset when the download becomes ready. A failed refresh is not charged. The file stays downloadable for 24 hours. See pricing.
Start a run
To choose the targets yourself, send the parameters below as input. The call returns 202 with the run; the key needs the scrapers:run scope and the account a positive credit balance.
curl -X POST "https://api.pandorlabs.com/v1/scrapers/realtor-agents/runs" \ -H "Authorization: Bearer $PANDORLABS_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": { "postalCodes": [ "78702" ], "types": "agent", "sort": "recent_activity_high", "requireContact": false } }'A run is billed at the live rate once it finishes: 2 credits per 100 rows it collected. A run that collects nothing costs nothing.
Parameters
Every parameter is optional. Anything you leave out uses the default shown here; an unknown name or an invalid value is rejected with a 400 that lists each problem.
Targeting
postalCodesstring[]
ZIP codes
One search per code. The endpoint searches by postal code only.
- Default
["78702"]- Example
78702, 78704
typesenum
Result type
Offices and teams are organisations rather than people, and carry far fewer fields.
- Default
agent- Allowed values
agentofficeteam
sortenum
Sort order
Only matters when a ceiling stops the sweep early — it decides which agents you keep.
- Default
recent_activity_high- Allowed values
recent_activity_highagent_rating_highrecommendations_count_highfor_sale_price_highfor_sale_price_lowrecently_sold_highreview_count_high
namestring
Name contains
Applied by realtor.com's own search, not locally.
- Default
- none
requireContactboolean
Require an email or phone
Drops profiles with no published contact details.
- Default
false
Advanced
narOnlyboolean
NAR members only
Only licensed REALTORS. The site sends this on by default.
- Default
true
photoOnlyboolean
Profiles with a photo only
- Default
true
agentRatingMinnumber
Minimum rating
- Default
- none
- Range
- 0 to 5
recommendationsCountMinnumber
Minimum recommendations
- Default
- none
- Range
- 0 to 1000
languagesstring[]
Languages
- Default
- none
- Example
es, zh
agentTypestring
Agent type
`buyer` or `seller`. Empty means both.
- Default
- none
- Example
buyer
priceMinnumber
Minimum transaction price
- Default
- none
- Range
- at least 0
priceMaxnumber
Maximum transaction price
- Default
- none
- Range
- at least 0
designationsstring[]
Designations
- Default
- none
- Example
ABR, CRS
maxAgentsPerPostalCodenumber
Max agents per ZIP
Rows persist and re-runs upsert, so a ceiling here bounds one run, not the dataset.
- Default
500- Range
- 1 to 10000
pageSizenumber
Page size
- Default
20- Range
- 1 to 50
requestDelayMsnumber
Delay between requests (ms)
realtor.com rate-limits aggressively per address. Lowering this earns 429s.
- Default
1500- Range
- 0 to 60000
jwtSecretstring
Token signing secret
The secret realtor.com's own frontend signs its request token with. Set this if they rotate it.
- Default
17ad51b0-08c3-4263-a711-d94477ad7ea3
Input as JSON Schema
The same schema the API validates against. Use it as a tool input schema or to generate a typed client.
{ "type": "object", "additionalProperties": false, "properties": { "postalCodes": { "type": "array", "items": { "type": "string" }, "maxItems": 1000, "title": "ZIP codes", "description": "One search per code. The endpoint searches by postal code only.", "default": [ "78702" ], "examples": [ "78702, 78704" ] }, "types": { "type": "string", "enum": [ "agent", "office", "team" ], "title": "Result type", "description": "Offices and teams are organisations rather than people, and carry far fewer fields.", "default": "agent" }, "sort": { "type": "string", "enum": [ "recent_activity_high", "agent_rating_high", "recommendations_count_high", "for_sale_price_high", "for_sale_price_low", "recently_sold_high", "review_count_high" ], "title": "Sort order", "description": "Only matters when a ceiling stops the sweep early — it decides which agents you keep.", "default": "recent_activity_high" }, "name": { "type": "string", "maxLength": 2000, "title": "Name contains", "description": "Applied by realtor.com's own search, not locally." }, "requireContact": { "type": "boolean", "title": "Require an email or phone", "description": "Drops profiles with no published contact details.", "default": false }, "narOnly": { "type": "boolean", "title": "NAR members only", "description": "Only licensed REALTORS. The site sends this on by default.", "default": true }, "photoOnly": { "type": "boolean", "title": "Profiles with a photo only", "default": true }, "agentRatingMin": { "type": "number", "minimum": 0, "maximum": 5, "title": "Minimum rating" }, "recommendationsCountMin": { "type": "number", "minimum": 0, "maximum": 1000, "title": "Minimum recommendations" }, "languages": { "type": "array", "items": { "type": "string" }, "maxItems": 1000, "title": "Languages", "default": [], "examples": [ "es, zh" ] }, "agentType": { "type": "string", "maxLength": 2000, "title": "Agent type", "description": "`buyer` or `seller`. Empty means both.", "examples": [ "buyer" ] }, "priceMin": { "type": "number", "minimum": 0, "title": "Minimum transaction price" }, "priceMax": { "type": "number", "minimum": 0, "title": "Maximum transaction price" }, "designations": { "type": "array", "items": { "type": "string" }, "maxItems": 1000, "title": "Designations", "default": [], "examples": [ "ABR, CRS" ] }, "maxAgentsPerPostalCode": { "type": "number", "minimum": 1, "maximum": 10000, "title": "Max agents per ZIP", "description": "Rows persist and re-runs upsert, so a ceiling here bounds one run, not the dataset.", "default": 500 }, "pageSize": { "type": "number", "minimum": 1, "maximum": 50, "title": "Page size", "default": 20 }, "requestDelayMs": { "type": "number", "minimum": 0, "maximum": 60000, "title": "Delay between requests (ms)", "description": "realtor.com rate-limits aggressively per address. Lowering this earns 429s.", "default": 1500 }, "jwtSecret": { "type": "string", "maxLength": 2000, "title": "Token signing secret", "description": "The secret realtor.com's own frontend signs its request token with. Set this if they rotate it.", "default": "17ad51b0-08c3-4263-a711-d94477ad7ea3" } }}Run, poll, read rows
The run is asynchronous. Poll it until it reaches a terminal status and its billing is paid, then page through its rows. Until then the rows endpoint answers 409 (still queued or running) or 402 (payment required).
RUN_ID=$(curl -s -X POST "https://api.pandorlabs.com/v1/scrapers/realtor-agents/runs" \ -H "Authorization: Bearer $PANDORLABS_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": { "postalCodes": [ "78702" ], "types": "agent", "sort": "recent_activity_high", "requireContact": false } }' | jq -r '.id')while true; do RUN=$(curl -s "https://api.pandorlabs.com/v1/runs/$RUN_ID" \ -H "Authorization: Bearer $PANDORLABS_KEY") STATUS=$(echo "$RUN" | jq -r '.status') BILLING=$(echo "$RUN" | jq -r '.billing.status') case "$STATUS" in queued|running) ;; *) [ "$BILLING" != "pending" ] && break ;; esac sleep 5doneecho "$RUN" | jq '{status, rowCount, billing}'curl -s "https://api.pandorlabs.com/v1/runs/$RUN_ID/rows?page=1&limit=100" \ -H "Authorization: Bearer $PANDORLABS_KEY"See the API reference for pagination, cancelling and listing runs.
Output fields
Rows have no fixed schema; these are the fields observed in the rows collected so far. Coverage is the share of rows where the field is present.
No rows collected yet, so no fields have been observed. Run the scraper once and they will appear here.
