logoPandorLabs
Real Estate

Realtor.com Agent Directory

US real estate agent profiles by ZIP code — brokerage, licences, contact details and transaction volume.

realtor-agentsrealtor.comreal-estateagentsdirectorylead-generationusa

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

The 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

  • postalCodes

    string[]

    ZIP codes

    One search per code. The endpoint searches by postal code only.

    Default
    ["78702"]
    Example
    78702, 78704
  • types

    enum

    Result type

    Offices and teams are organisations rather than people, and carry far fewer fields.

    Default
    agent
    Allowed values
    agent
    office
    team
  • sort

    enum

    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_high
    agent_rating_high
    recommendations_count_high
    for_sale_price_high
    for_sale_price_low
    recently_sold_high
    review_count_high
  • name

    string

    Name contains

    Applied by realtor.com's own search, not locally.

    Default
    none
  • requireContact

    boolean

    Require an email or phone

    Drops profiles with no published contact details.

    Default
    false

Advanced

  • narOnly

    boolean

    NAR members only

    Only licensed REALTORS. The site sends this on by default.

    Default
    true
  • photoOnly

    boolean

    Profiles with a photo only

    Default
    true
  • agentRatingMin

    number

    Minimum rating

    Default
    none
    Range
    0 to 5
  • recommendationsCountMin

    number

    Minimum recommendations

    Default
    none
    Range
    0 to 1000
  • languages

    string[]

    Languages

    Default
    none
    Example
    es, zh
  • agentType

    string

    Agent type

    `buyer` or `seller`. Empty means both.

    Default
    none
    Example
    buyer
  • priceMin

    number

    Minimum transaction price

    Default
    none
    Range
    at least 0
  • priceMax

    number

    Maximum transaction price

    Default
    none
    Range
    at least 0
  • designations

    string[]

    Designations

    Default
    none
    Example
    ABR, CRS
  • maxAgentsPerPostalCode

    number

    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
  • pageSize

    number

    Page size

    Default
    20
    Range
    1 to 50
  • requestDelayMs

    number

    Delay between requests (ms)

    realtor.com rate-limits aggressively per address. Lowering this earns 429s.

    Default
    1500
    Range
    0 to 60000
  • jwtSecret

    string

    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.

inputSchema
{  "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.

© 2026 PandorLabs LLC. All rights reserved.