# Realtor.Com Agent Scraper With Phone Social Leads (`api-empire/realtor-com-agent-scraper`) Actor

Realtor.com Agent Scraper extracts real estate agent profiles, phone numbers, social links, names, specialties, locations, ratings, and profile URLs. Ideal for real estate lead generation, agent prospecting, contact discovery, market research, and competitive intelligence.

- **URL**: https://apify.com/api-empire/realtor-com-agent-scraper.md
- **Developed by:** [API Empire](https://apify.com/api-empire) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Realtor.com Agent Scraper — Leads, Social Links & Broker Data

Realtor.com Agent Scraper With Phone & Social Leads turns a list of ZIP codes into one callable lead row per real estate agent — name, office and mobile phone, brokerage, listing and sold counts, review count, and profile links across six social platforms whenever the agent publishes them. Every response is typed, normalized JSON — no HTML, no selectors, no parsing. Optional filters drop agents with no phone number and merge duplicate agents found under several nearby ZIP codes into a single row. After reading this, you will know exactly which fields come from Realtor.com's own API, which are computed, and — plainly, because it matters — which field does not do what its name implies.

### What is Realtor.com Agent Scraper With Phone & Social Leads?

It is an Apify Actor that queries Realtor.com's own agent-search and agent-branding endpoints for one or more ZIP codes and writes one dataset row per agent found. No Realtor.com account or login is involved — the Actor reads the same public buyer's-agent directory a browser gets when you search Realtor.com by ZIP, using an internal GraphQL API rather than rendered pages.

- Scrape **agent contact leads** — name, office phone, mobile phone(s), listing count, sold count, review count
- Scrape **social profile links** — Facebook, Instagram, LinkedIn, X, YouTube and TikTok, per agent
- Scrape **brokerage / office data** — company name, company website, areas serviced
- Filter to phone-only leads, and merge the same agent found under multiple ZIP codes into one row
- Export as JSON, CSV or Excel — no proxy management, no parsing

### What data does Realtor.com Agent Scraper collect?

Three groups of data land on every row: who the agent is and how reachable they are, where their social presence lives, and who they work for.

| Data Type | Key Fields | JSON Field Names |
| ----- | ----- | ----- |
| Agent contact leads | Name (with realtor/non-realtor label), office and mobile phone, listing count, sold count, review count, phone-qualified flag | `agent_name`, `office_phone`, `mobile_phones`, `has_phone`, `listing_count`, `sold_count`, `review_count`, `agent_photo` |
| Social profile links | One URL per platform, plus a has-any-social flag | `facebook_url`, `instagram_url`, `linkedin_url`, `x_url`, `youtube_url`, `tiktok_url`, `has_social` |
| Brokerage / office data | Company name, company website, areas served, ZIP codes the row was matched under | `office_company_name`, `company_website`, `areas_serviced`, `zip_code`, `zips_served` |

#### Need more Realtor.com data?

This Actor covers the buyer-side agent directory by ZIP. If your outreach list needs the property side too — active listings, price history, MLS numbers, recently-sold comps — pair it with a Realtor.com property scraper from the Apify Store; nothing in this account currently covers Realtor.com property listings, so that gap is worth naming rather than papering over. For local-business contact enrichment outside real estate, **Google Maps Scraper With Lead & Contact Enrichment** and **Facebook Search Scraper WhatsApp Contact Leads** return contact fields in a comparable shape.

### Why not build this yourself?

Realtor.com/Move, Inc. does not publish a public, key-authenticated API for searching its agent directory by ZIP code. The only path to this data is the same internal GraphQL gateway (`/frontdoor/graphql`, operations `SearchAgents` and `AgentBrandingProfile`) that realtor.com's own website calls — and the Actor's source notes that this endpoint sits behind an Akamai/PerimeterX-class WAF that fingerprints a plain `requests`/`aiohttp` client at the TLS/JA3 level and answers with either a 403 or a data-less HTTP-200 shell. A DIY script needs Chrome-accurate TLS impersonation just to get a real response, then has to tell that shell apart from a legitimate "no more agents" page — the two look identical at the HTTP-status level and only differ in whether the GraphQL `data` container is present.

Past that first hurdle is the maintenance load: two undocumented GraphQL operations that can add, rename or nest a field at any time, and an anti-bot layer that can escalate its blocking posture without notice. Realtor.com Agent Scraper absorbs both — the query shapes and the block-detection logic are maintained centrally instead of inside your own script.

### Why do developers and teams scrape Realtor.com agent data?

A ZIP-scoped agent directory with phone and social links attached serves a narrower set of buyers than a general listings scraper — mostly people building or feeding a realtor contact list.

#### For recruiting brokerages and team leads

Brokerages sourcing producing agents in a target market pull `sortOrder: MOST_SALES` or `RATINGS_REVIEWS` for a set of ZIP codes, then rank candidates on `listing_count`, `sold_count` and `review_count` before a single recruiting call is made. `office_company_name` shows which brokerage an agent currently sits at, so a recruiting list can be filtered to exclude — or specifically target — a competitor's roster.

#### For B2B vendors and sales teams

Title and escrow companies, mortgage brokers, transaction coordinators, real-estate photographers and proptech vendors all sell into the same buyer: an active agent. `requirePhone` keeps only agents with a dialable number, `dedupeAgents` collapses an agent found under five nearby ZIPs into one CRM record with `zips_served` listing all five, and the social URLs give an outreach team a second channel — a LinkedIn connection request or an Instagram DM — when a cold call goes unanswered.

#### For market researchers and analysts

`listing_count`, `sold_count` and `review_count` per ZIP, aggregated across a metro area, are a public proxy for agent density and production concentration in a market — useful for tracking which brokerages dominate which ZIP codes without touching any gated MLS data. Sweep the same ZIP set on a schedule and diff `sold_count` per agent over time to see production shift.

#### For AI engineers and developers building data products

Every row is fixed-schema JSON with the same 23 keys on every run, so a tool definition written once against this Actor's output stays valid. Index `agent_name`, `office_company_name` and `areas_serviced` into a vector store and an agent can answer "which agents in ZIP 90211 have sold the most homes this year" against live data instead of a stale export.

### How to scrape Realtor.com agent leads (step by step)

This Actor runs on Apify. Start it from the **Apify Console**, or call it through the **Apify API** with your Apify token. There is no separate signup, no Realtor.com credential, and no other run surface.

1. Open **Realtor.com Agent Scraper With Phone & Social Leads** on the Apify Store and click **Try for free**.
2. Fill in **📮 Target Zip Codes** (`zipCodes`) — the only required input. Add as many ZIPs as you need; each is searched independently.
3. Set **🎯 Leads Per Zip Code** (`maxItemsPerZipcode`) and **↕️ Result Ranking** (`sortOrder`) to control volume and how Realtor.com orders the results within each ZIP.
4. Toggle **🔗 Extract Social Profile Links**, **📞 Only Agents With a Phone Number** and **🧹 Merge Duplicate Agents Across Zip Codes** to shape the lead list.
5. Click **Start**. Rows land in the dataset as each agent is processed. Export as JSON, CSV or Excel, or read the dataset through the Apify API.

#### What to do when Realtor.com changes its structure

Nothing on your side. The Actor is maintained against Realtor.com's GraphQL operations, and the output keys stay the same across updates, so your integration keeps working without a schema change on your end.

### ⬇️ Input

Eight parameters, read directly from the Actor's input schema. Only `zipCodes` is required.

| Parameter | Required | Type | Description | Example Value |
| ----- | ----- | ----- | ----- | ----- |
| `zipCodes` | ✅ Yes | array of strings | ZIP codes to pull agent leads from. Add as many as you like — each is searched separately. Editor is a string list; the Console form prefills `["07101", "00501"]`. No default. | `["07101", "90211"]` |
| `maxItemsPerZipcode` | No | integer | How many agents to collect from each ZIP code before moving on. Minimum `1`, maximum `10000`, **default `10`**. | `25` |
| `sortOrder` | No | string (enum) | Order Realtor.com returns agents in for each ZIP. One of `RELEVANT_AGENTS` (Most Relevant), `RATINGS_REVIEWS` (Top Rated / Most Reviews), `MOST_SALES` (Most Sales), `MOST_RECENT_ACTIVITY` (Most Recent Activity), `TESTIMONIALS_RECOMMENDATIONS` (Most Testimonials & Recommendations). **Default `"RELEVANT_AGENTS"`**. | `"RATINGS_REVIEWS"` |
| `includeSocialLinks` | No | boolean | Adds Facebook, Instagram, LinkedIn, X, YouTube and TikTok profile URLs to each agent lead, whenever the agent publishes them. Turn off for a lighter, contact-only export. **Default `true`**. | `true` |
| `requirePhone` | No | boolean | Drops any agent with no mobile or office phone, so every exported lead is callable. **Default `false`** (keep all). | `true` |
| `dedupeAgents` | No | boolean | The same agent often appears under several nearby ZIP codes. On: output one merged row per agent, with every ZIP they were found under listed in `zips_served`. **Default `false`** (one row per agent per ZIP). | `true` |
| `maxRetries` | No | integer | How many times to retry a blocked or unstable request before giving up. Minimum `1`, maximum `10`, **default `3`**. | `5` |
| `proxyConfiguration` | No | object (proxy editor) | Apify Proxy settings. Prefilled `{"useApifyProxy": false}` — the Actor starts on a direct connection and escalates automatically to datacenter, then sticky residential, if Realtor.com blocks it. Enable Apify Proxy to start proxied from the first request. | `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` |

#### Behaviour worth knowing before you configure it

- **⚠️ `maxRetries` is currently not wired to the retry logic.** The value is read from your input, validated against its 1–10 range, and printed in the run log — but the functions that actually perform the retries (`search_agents_with_retry`, `fetch_agent_detail_with_retry`) are called without it and fall back to their own hardcoded default of **3 attempts**, regardless of what you set here. Setting `maxRetries` to `10` does not currently make the Actor retry more than 3 times. This is documented here rather than hidden so you can plan around it — every request gets 3 attempts through the proxy escalation ladder no matter what.
- **The agent search is buyer-side only, and this is not exposed as an input.** The underlying GraphQL query hardcodes `agent_type: ['BUYER']`; there is no `sortOrder`-style toggle to request seller's agents. `matching_rows` for a ZIP reflects buyer-side agents only.
- **`zipCodes` also silently accepts a `zipCodesList` key** as a fallback if `zipCodes` is empty or absent — an undocumented compatibility alias left in the code from an earlier input-schema name. The published schema only defines `zipCodes`; use that key.
- **`maxItemsPerZipcode`'s in-code fallback (`100`) does not match the schema default (`10`).** If the key is ever missing from the raw input object entirely, the code falls back to 100 rather than the schema's declared default of 10. In normal use through the Apify Console or API, Apify applies the schema default before your run starts, so this is unlikely to surface — but it is a real discrepancy in the source.

#### Example input

```json
{
  "zipCodes": ["07101", "90211"],
  "maxItemsPerZipcode": 25,
  "sortOrder": "RATINGS_REVIEWS",
  "includeSocialLinks": true,
  "requirePhone": true,
  "dedupeAgents": true,
  "maxRetries": 3,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

**Common pitfall:** expecting `website` in the output to be the agent's personal or brokerage-branded site because `includeSocialLinks` and the social fields are on. It never is — see the field notes under Output below before you build an outreach flow around it.

### ⬆️ Output

Every agent is one flat dataset row with the same **23 keys**, run after run. Export as JSON, CSV or Excel, or read the dataset through the Apify API. Social fields come back `null` when the agent does not publish that platform — the Actor never fabricates a link — and `email` is always `null` because Realtor.com's agent API does not expose it.

#### Scraped agent lead

```json
{
  "agent_name": "Jane Smith, agent",
  "website": "https://www.realtor.com/realestateagents/123456",
  "email": null,
  "listing_count": 12,
  "sold_count": 34,
  "office_phone": "(310) 555-0100",
  "mobile_phones": "(310) 555-0142",
  "areas_serviced": "Beverly Hills, West Hollywood, Bel Air",
  "zip_codes_serviced": null,
  "office_company_name": "Compass",
  "company_website": "https://www.compass.com",
  "review_count": 41,
  "agent_photo": "https://ap.rdcpix.com/1671514694/photo-w144_h144.jpg",
  "facebook_url": "https://www.facebook.com/janesmithrealtor",
  "instagram_url": "https://www.instagram.com/janesmithhomes",
  "linkedin_url": "https://www.linkedin.com/in/janesmith",
  "x_url": null,
  "youtube_url": null,
  "tiktok_url": null,
  "has_social": true,
  "has_phone": true,
  "zips_served": "90211",
  "zip_code": "90211"
}
```

#### Deduplicated agent lead (`dedupeAgents: true`)

Same 23 keys. When the same agent is matched under more than one ZIP in the run, one row is written instead of several, `zips_served` lists every ZIP they were found under, and `zip_code` is set to the first ZIP that matched them:

```json
{
  "agent_name": "Marcus Reyes, agent",
  "website": "https://www.realtor.com/realestateagents/987654",
  "email": null,
  "listing_count": 19,
  "sold_count": 27,
  "office_phone": "(973) 555-0110",
  "mobile_phones": "(973) 555-0187",
  "areas_serviced": "Newark, Irvington, East Orange",
  "zip_codes_serviced": null,
  "office_company_name": "Keller Williams Realty",
  "company_website": "https://www.kw.com",
  "review_count": 22,
  "agent_photo": "https://ap.rdcpix.com/1671514694/photo2-w144_h144.jpg",
  "facebook_url": null,
  "instagram_url": "https://www.instagram.com/reyeshomesnj",
  "linkedin_url": null,
  "x_url": null,
  "youtube_url": null,
  "tiktok_url": null,
  "has_social": true,
  "has_phone": true,
  "zips_served": "07101, 07018, 07017",
  "zip_code": "07101"
}
```

#### ⚠️ Field notes — read this before building outreach off `website`

- **`website` is not the agent's real website — this is a confirmed behaviour, not a display choice.** The Actor's `AgentBrandingProfile` GraphQL query does request the agent's actual `website` field from Realtor.com's API (`src/main.py`, GraphQL query body, the `website` field directly under `branding`). But the row-building function never reads that value. Instead it constructs `website` as `f"https://www.realtor.com/realestateagents/{fulfillment_id}"` — a link to the agent's own Realtor.com profile page — and that constructed link is what gets pushed under the `website` key (`src/main.py`, `extract_agent_details()`, the "Construct website URL" block, immediately followed by `"website": website` in the returned row). The real agent-published website that the query fetched is discarded and never surfaces on any output field. If your workflow needs an agent's actual personal or team website — for a mail-merge, a site audit, or a "does this agent have a site" filter — `website` will not give it to you; treat it strictly as a Realtor.com profile link.
- **`company_website`, by contrast, is real** — it is the office's or broker's own website (`office.website`, falling back to `broker.website`), read directly from the API response with no substitution.
- **`agent_name` carries a suffix, not just the name.** It is built as `"{fullname}, agent"` when the agent is a licensed Realtor, or `"{fullname}, non-realtor"` otherwise — split it on the last comma if you need the bare name.
- **`email` is always `null`.** Realtor.com's agent API does not publish agent email addresses anywhere the Actor's queries reach; the field exists in every row for schema consistency, not because it is ever populated.
- **`zip_codes_serviced` is always `null`.** It is a placeholder field carried over from the row schema; the Actor does not compute or populate it from any Realtor.com response. Use `areas_serviced` (city/area names) or `zips_served` (the ZIPs the row itself was matched under) instead.
- **`mobile_phones` is a comma-joined string, not an array.** An agent with two mobile numbers on file returns `"(555) 111-2222, (555) 333-4444"` as one string field.
- **`office_phone` prefers the office's own listed phone**, falling back to the agent's personal record marked `type: office` only when the office has none on file.

### How does Realtor.com Agent Scraper compare to other Realtor.com scrapers?

| Feature | This Actor | Generic alternative |
| ----- | ----- | ----- |
| Social profile links | ✅ Six platforms (`facebook_url` … `tiktok_url`), fetched in the same request as the rest of the profile, no extra charge | Commonly absent, or a single generic "social" field |
| Phone-only qualification | ✅ `requirePhone` drops unreachable agents before the row is charged | Typically returned unfiltered — you filter after paying for every row |
| Cross-ZIP deduplication | ✅ `dedupeAgents` merges one agent found under several ZIPs into one charged row with a merged `zips_served` list | Typically one row per ZIP match, duplicate agents included |
| Website field honesty | ⚠️ `website` is a Realtor.com profile link, not the agent's real site — documented plainly above | Varies by scraper; check what each actually returns before assuming |
| Search scope | Buyer-side agents only, fixed in the query | Some competitors expose a buyer/seller toggle |

Three named listings, checked on the Apify Store **2026-07-25** — the figures below are what each lists on its own page, not measured here:

- **`gocreative.ai/realtor-com-pro-leads`** — its listing documents a narrower field set per record (name, brokerage, phone, profile URL, service area, recent activity) and does not document social profile extraction.
- **`blackfalcondata/realtor-agents-scraper`** — its listing documents an `agentType` input (`BUYER` or `SELLER`, default `BUYER`), an `agentLanguages` filter, license number and state fields, notification webhooks (Telegram, Slack, Discord), and an MCP connector to Notion — a broader feature surface than this Actor, at pay-per-event pricing of $0.003 per run start plus $0.0012 per result as stated on its listing.
- **`scrapesage/realtor-com-scraper`** — its listing is primarily a property scraper (for-sale, for-rent, sold) with an opt-in `agentLeads` output mode that documents `email`, `website` and a computed `leadScore` per agent lead, sourced from listing-agent contact cards rather than a ZIP-scoped agent directory search.

If you're building an AI agent or RAG pipeline, the output-format row is the decision-maker — parsing HTML inside an agent loop is a reliability failure mode, not a feature. If your workflow specifically needs an agent's real personal website, `email`, or a seller-side search, none of the above is guaranteed from this Actor as configured today — check the field notes above and the competitor claims here against your actual requirement before choosing.

### How many results can you scrape with Realtor.com Agent Scraper?

`maxItemsPerZipcode` caps the number of agents saved **per ZIP code**, with a minimum of `1`, a maximum of `10000`, and a default of `10`. It is a per-ZIP figure, not a run-wide total — five ZIP codes at `maxItemsPerZipcode: 25` can save up to 125 rows (fewer if `requirePhone` or `dedupeAgents` reduce the count, or if a ZIP simply has fewer agents than that).

Pagination is handled automatically: Realtor.com's `SearchAgents` operation returns 24 agents per page, and the Actor keeps requesting pages for a ZIP — with a jittered delay between pages — until it reaches `maxItemsPerZipcode`, exhausts the ZIP's `matching_rows` total, or a page comes back empty. There is no separate offset or page-number input to manage; it is entirely driven by `maxItemsPerZipcode`.

Two practical ceilings follow. A ZIP code with few active buyer's agents on file will return short of your target — that is Realtor.com's own directory being thin for that area, not a run failure. And because the search is fixed to buyer-side agents (see Input notes above), `matching_rows` for any ZIP reflects that subset, not the full number of licensed agents active there.

### Integrate Realtor.com Agent Scraper and automate your workflow

Realtor.com Agent Scraper works with any language or tool that can send an HTTP request to the Apify API.

#### REST API integration

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("<YOUR_USERNAME>/realtor-com-agent-scraper-with-phone-social-leads").call(run_input={
    "zipCodes": ["07101", "90211"],
    "maxItemsPerZipcode": 25,
    "sortOrder": "RATINGS_REVIEWS",
    "requirePhone": True,
    "dedupeAgents": True,
})

for agent in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(agent["agent_name"], agent["office_phone"], agent["office_company_name"])
```

Works in Python, Node.js, Go, Ruby, cURL.

#### Automation platforms (n8n, Make, LangChain)

In **n8n**, use the Apify node — or an HTTP Request node against the Apify run endpoint with your token — passing the same JSON input shown above; a Filter node on `has_phone` and `has_social` narrows the dataset to fully-qualified leads before it hits a CRM node. In **Make**, the Apify module's run-and-wait mode feeds an Iterator over the dataset items straight into a Google Sheets, Airtable or HubSpot module for a weekly territory sweep. In **LangChain**, wrap the Apify run call as a tool and pass rows to the model unchanged — they are already typed JSON with fixed keys.

### Is it legal to scrape Realtor.com agent profiles?

Scraping publicly available directory information is broadly treated as permissible where the data is accessible without authentication, and this Actor collects only what an anonymous visitor already sees on Realtor.com's public agent-search pages — no login, no cookie, no account.

The output is personal data about identifiable individuals — licensed real estate agents' names, phone numbers and photos — even though the context is professional. That means data-protection regimes such as **GDPR and CCPA** can apply to how you store and use it, depending on your jurisdiction and the agent's. You need a lawful basis for storage and any outreach use, and marketing to the numbers you collect is subject to the anti-spam and telemarketing rules of the recipient's jurisdiction (e.g., TCPA-style consent rules in the US).

Consult legal counsel for commercial use cases involving bulk personal data.

### ❓ Frequently asked questions

#### Does Realtor.com Agent Scraper work without a Realtor.com account?

Yes. No Realtor.com account, login or cookie is used. The Actor sends requests to Realtor.com's public agent-search GraphQL endpoint with Chrome-impersonated TLS. The only credential you need is your Apify token, and only if you start the run through the API rather than clicking Start in the Console.

#### How often is the scraped data updated?

Every run fetches live. Nothing is cached between runs or between ZIP codes within a run — each `SearchAgents` and `AgentBrandingProfile` call goes out fresh, so a row reflects what Realtor.com published at the moment your run touched it. Use Apify's scheduler for a recurring refresh.

#### What happens when a ZIP code has no agents, or a request keeps getting blocked?

If a ZIP genuinely has no matching agents, the Actor logs it and moves to the next ZIP — no row is written for that ZIP, and the run continues normally. If the very first page of results for a ZIP fails after exhausting its retry attempts (a persistent block, not "no results"), the Actor raises and the run ends — any ZIP codes already processed keep their pushed rows in the dataset (unless `dedupeAgents` is on, see below), but ZIP codes later in your list are not attempted.

#### Does `dedupeAgents` change what happens if the run fails partway through?

Yes, and it's worth knowing before a long multi-ZIP run. With `dedupeAgents` off, each row is pushed to the dataset immediately as it's processed, so a mid-run failure still leaves you with every row completed so far. With `dedupeAgents` on, rows are buffered in memory and only written — merged, one per unique agent — after every ZIP code in your list has been processed. If the run fails before that final flush, **no rows have been saved yet**, even if hundreds of agents were already fetched.

#### Can I scrape seller's-side agents, or agents by name or city?

No, not with this Actor as it currently ships. The agent search is fixed to buyer's agents by ZIP code (`agent_type: ['BUYER']` in the underlying query, with no seller toggle exposed), and there is no name or city/state search input — `zipCodes` is the only search axis. This is a genuine constraint of the current input schema, not a filter you can work around from the Console.

#### Does Realtor.com Agent Scraper work for AI agent workflows and LLM pipelines?

Yes. It is a standard HTTP-triggered Apify Actor, so LangChain, CrewAI, n8n or a hand-written tool definition can start a run through the Apify API and read typed JSON back with no parsing step. Every row has the same 23 keys, so a tool schema written once stays valid.

#### How does Realtor.com Agent Scraper handle Realtor.com's anti-bot system?

Requests are sent with Chrome TLS/JA3 impersonation (`curl_cffi`, Chrome 124 profile) rather than a default HTTP client signature. A response is treated as blocked on HTTP `403`, `429` or `503`, on a non-JSON body, or on a data-less 200 shell (missing the GraphQL `data` container) — the last case matters because it is what Realtor.com's WAF returns instead of a clean error, and misreading it as "no more results" would silently truncate a run. On a block the Actor escalates one rung — direct connection → Apify datacenter proxy → Apify residential proxy — and once it reaches residential it stays there (sticky) for the remainder of the run. Between pages and between processing batches, requests carry a randomised delay to reduce the rate of blocking in the first place.

#### How does Realtor.com Agent Scraper compare to other Realtor.com scrapers?

Checked on the Apify Store on 2026-07-25: `blackfalcondata/realtor-agents-scraper` documents the broadest feature surface of the three named competitors — a buyer/seller toggle, language filtering, license fields and notification webhooks. `gocreative.ai/realtor-com-pro-leads` documents a narrower field set with no social extraction. `scrapesage/realtor-com-scraper` is primarily a property listings scraper with an agent-lead side mode. This Actor's difference is depth on the agent-and-social side specifically — six social platforms per row plus phone-only filtering and cross-ZIP dedupe — at the cost of being buyer-side and ZIP-only by search scope. See the comparison table above for specifics.

#### Does Realtor.com Agent Scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with the same field names on every run. No HTML, no selectors, no parsing. Pass a row straight into an LLM context window, index it into a vector store, or hand it to an agent tool.

#### Can I use Realtor.com Agent Scraper without managing proxies?

Yes. Leave `proxyConfiguration` at its default and the Actor starts on a direct connection, detects blocking, and escalates to Apify datacenter and then Apify residential proxies on its own, holding residential once it gets there. Enable Apify Proxy in the input to start proxied from the first request instead.

#### What happens when Realtor.com changes its structure or blocks the scraper?

The scraper is maintained, and the output keys stay the same across updates, so your field names and types don't change on your end. No numeric turnaround time is promised here.

### 💳 Pricing and what gets charged

This Actor uses Apify's **pay-per-event** pricing with a single event: **`row_result`**, charged once for each agent row written to the dataset.

**You are not charged for:**

- Agents dropped by `requirePhone` — the phone check runs before the push, so a phone-only run never pays for agents it is about to filter out.
- ZIP codes that return no matching agents.
- Blocked or retried requests, and proxy fallback attempts.

**The one nuance to plan around:** with `dedupeAgents` on, the same agent found under three different ZIP codes is charged **once**, as a single merged row — deduplication happens before the charge, not after. With `dedupeAgents` off, the same agent found under three ZIP codes is charged three times, once per ZIP, because that is three separate rows by design. Choose the setting that matches how you want to pay as much as how you want the data shaped. Runs also consume standard Apify platform usage (compute units, plus proxy traffic if you enable Apify Proxy), billed by Apify in the usual way.

### 🔗 Related scrapers

| Scraper Name | What it extracts |
| ----- | ----- |
| Google Maps Scraper With Lead & Contact Enrichment | Local business listings with crawled emails, phones and social profiles |
| Facebook Search Scraper WhatsApp Contact Leads | Facebook search results with WhatsApp contact leads |
| LinkedIn Phone Email Finder | Phone and email contact points for LinkedIn profiles |
| Instagram Local Phone Leads Scraper | Local business Instagram profiles with published phone contacts |
| Apartments.com Scraper Neighborhood Rent & Livability Report | Rental listing and neighborhood data from Apartments.com |

### 💬 Your feedback

Found a bug, or missing a field that Realtor.com publishes but the output does not carry? We want to know — open an issue on the Actor's **Issues** tab and it will be looked at. Reports that include the exact input JSON you ran, and the ZIP code or agent name of a row that came out wrong, are the fastest to reproduce and fix.

# Actor input Schema

## `zipCodes` (type: `array`):

Zip codes to pull agent leads from. Add as many as you like — each is searched separately. Example: \["07101", "90211"].

## `maxItemsPerZipcode` (type: `integer`):

How many agents to collect from each zip code before moving on. Example: 25 → up to 25 agent leads per zip. Default is 10.

## `sortOrder` (type: `string`):

Order in which Realtor.com returns agents for each zip. RATINGS\_REVIEWS and TESTIMONIALS\_RECOMMENDATIONS surface higher-quality leads (which also carry the most social links). Default is RELEVANT\_AGENTS.

## `includeSocialLinks` (type: `boolean`):

Add Facebook, Instagram, LinkedIn, X, YouTube and TikTok profile URLs to each agent lead (whenever the agent publishes them). Turn off for a lighter, contact-only export. Default is true.

## `requirePhone` (type: `boolean`):

Drop any agent that has no mobile or office phone, so every exported lead is callable. Example: 24 found, 3 phoneless → 21 rows. Default is false (keep all).

## `dedupeAgents` (type: `boolean`):

The same agent often appears under several nearby zip codes. Turn on to output ONE merged row per agent, with every zip they were found under listed in 'zips\_served'. Default is false (one row per agent per zip).

## `maxRetries` (type: `integer`):

How many times to retry a blocked or unstable request (rotating proxy IP) before giving up. Default is 3.

## `proxyConfiguration` (type: `object`):

Starts with a direct connection. If Realtor.com's anti-bot layer blocks a request, the actor automatically escalates to datacenter, then sticky residential proxies. Enable Apify Proxy here to start proxied from the first request.

## Actor input object example

```json
{
  "zipCodes": [
    "07101",
    "00501"
  ],
  "maxItemsPerZipcode": 10,
  "sortOrder": "RELEVANT_AGENTS",
  "includeSocialLinks": true,
  "requirePhone": false,
  "dedupeAgents": false,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped agent leads in the Actor's default dataset, one row per agent (or per merged agent when de-duplication is enabled).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "zipCodes": [
        "07101",
        "00501"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("api-empire/realtor-com-agent-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "zipCodes": [
        "07101",
        "00501",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("api-empire/realtor-com-agent-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "zipCodes": [
    "07101",
    "00501"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call api-empire/realtor-com-agent-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,api-empire/realtor-com-agent-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/4JYBmEVopg7UTAvxX/builds/7GU6kxGIjiBzwoMWf/openapi.json
