# Zillow Agents Scraper (`datascrapers/zillow-agents-scraper`) Actor

Extract Zillow real estate agent data by zip code, city, or state. Optionally enrich records with full agent profiles including listings, reviews, licenses, and contact details.

- **URL**: https://apify.com/datascrapers/zillow-agents-scraper.md
- **Developed by:** [Data Scrapers](https://apify.com/datascrapers) (community)
- **Stats:** 2 total users, 1 monthly users, 64.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 dataset items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**Zillow Agents Scraper** creates a structured dataset of real estate agent contact records sourced from Zillow. Each dataset item is one agent and can include the agent name, brokerage, profile URL, rating, and sales summary. When detailed profiles are enabled, the same record can also include phone numbers, email, website, social links, brokerage address, licenses, and service areas. Query by US zip code, city, or state, control the result limit with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.

[![Zillow Agents Scraper — input to structured data](https://raw.githubusercontent.com/faizanalii/apify-actor-assets/main/zillow-agents-scraper/zillow-agents-scraper-value-demo.gif)](https://apify.com/datascrapers/zillow-agents-scraper)

### Dataset at a glance

| Property | Value |
|---|---|
| Source | Zillow agent index and public Zillow profile pages |
| Record unit | One real estate agent |
| Input methods | `zipCodes`, `cities`, or `states` |
| Main identifiers | `encodedZuid`, `cardActionLink` |
| Contact fields | Phone, email, website, and brokerage address on a successful detailed profile |
| Delivery | Apify Dataset and Dataset API |
| Export formats | JSON, CSV, Excel, XML, and other Apify dataset formats |
| Update model | Directory rows from the location index; profile contact fields fetched during the run |
| Pricing | `dataset-item` $1.50 / 1,000; `detailed-data` $2.00 / 1,000 before plan discounts |

### Coverage and available records

Use this dataset to build a territory contact list. A run needs at least one location. `zipCodes` accepts five-digit US zip codes that exist in the location index. `cities` accepts an exact `State, City` key, such as `Alaska, Anchorage`, or a city name matched at 98% similarity. `states` accepts a full state name from the input list. A location that is not in the index fails the run.

The location index shipped with this Actor lists 33,403 zip codes, 26,285 cities, and 49 states. Alabama is in the input list and is not in that index, so selecting Alabama fails the run. The index does not claim every agent currently published on Zillow.

Directory records are loaded from that index. They include the agent name, brokerage, profile URL, photo, top-agent flag, rating summary, sales summary, tags, and the state, city, and zip used for the lookup. They do not include phone or email.

Set `includeDetailedProfile` to `true` to open each agent's public profile URL and attach `detailedProfile`. That object is where lead fields live: `displayUser.phoneNumbers`, `displayUser.email`, `displayUser.businessAddress`, `professionalInformation` (cell phone, broker phone, websites, and licenses), and `getToKnowMe` website and social URLs. In observed enriched profiles those phone and email fields were present. They remain source fields and are absent when the profile page omits them or the fetch fails.

`maxItems` of `0` means no Actor-side cap, except on the Apify free plan. A free-plan run is limited to 2 directory records, detailed profiles are turned off, and each saved agent is marked `_trial`. The run also appends one upgrade message that is not an agent.

Agents are deduplicated inside the run by `cardActionLink`. A profile URL that fails to load is still saved as a directory record with `hasDetailedProfile` set to `false`. Listings, reviews, and past sales are included on a successful detailed profile and are not separate dataset items.

### Data dictionary

Directory fields are present on every agent record. The best field for deduplication is `cardActionLink`. `encodedZuid` is the Zillow user id and is the other stable identifier.

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `cardTitle` | string | Yes | Agent or team name from the directory card. | `Roy Briley Real Estate Group` |
| `secondaryCardTitle` | string | Yes | Brokerage name on the directory card. | `Real Estate Brokers of Alaska` |
| `cardActionLink` | string | No | Public Zillow profile URL. Deduplication key. | `https://www.zillow.com/profile/Roy%20Briley%20RE%20Group` |
| `encodedZuid` | string | Yes | Zillow encoded user id. | `X1-ZUzl3bfxwglz49_47pep` |
| `imageUrl` | string | Yes | Profile photo URL. | `https://photos.zillowstatic.com/fp/f1ca7d45cacd64fa44e69e15450b6d11-h_l.jpg` |
| `logoUrl` | string | Yes | Brokerage logo URL when the card includes one. | `null` |
| `isTopAgent` | boolean | Yes | Source top-agent flag. | `true` |
| `state` | string | Yes | State name stored with the directory row. | `Alaska` |
| `city` | string | Yes | City stored with the directory row. | `Anchorage` |
| `zip_code` | string | Yes | Zip code stored with the directory row. | `99501` |
| `page` | integer | Yes | Directory page number stored with the row. | `1` |
| `reviewInformation` | object | Yes | Rating summary. See nested fields. | |
| `profileData` | array | Yes | Sales and price-range lines from the card. | |
| `tags` | array | Yes | Card tags such as `TEAM`. | |
| `hasDetailedProfile` | boolean | Conditional | Present when detailed profiles are requested. `true` only after a profile page loads. | `true` |
| `detailedProfile` | object | Conditional | Full profile payload, including contact fields. Present only when the profile page loads. | |

#### `reviewInformation`

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `reviewAverage` | number | Yes | Numeric average rating. | `5` |
| `reviewAverageText` | string | Yes | Rating as display text. | `5.0` |
| `reviewCountFormattedText` | string | Yes | Review count as display text, including parentheses when the source sends them. | `(219)` |
| `noReviewsText` | string | Yes | Source empty-state text. Can still be present when reviews exist. | `No reviews` |

#### `profileData[]` and `tags[]`

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `profileData[].label` | string | Yes | Metric label from the card. | `team sales last 12 months` |
| `profileData[].formattedData` | string | Yes | Metric value as display text, not a parsed number. | `206` |
| `tags[].text` | string | Yes | Tag label. | `TEAM` |
| `tags[].tagType` | string | Yes | Source tag type. | `WARNING` |

#### Contact fields inside `detailedProfile`

These fields are the lead-generation portion of the record. They are absent unless `includeDetailedProfile` is `true` and the profile page loads.

#### `detailedProfile.displayUser`

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `name` | string | Yes | Profile display name. | `Roy Briley Real Estate Group` |
| `screenName` | string | Yes | Zillow screen name. | `Roy Briley RE Group` |
| `businessName` | string | Yes | Brokerage name on the profile. | `Real Estate Brokers of Alaska` |
| `email` | string | Yes | Email published on the profile. | `rbreg@akreba.com` |
| `phoneNumbers` | object | Yes | Published phone numbers. See nested fields. | |
| `businessAddress` | object | Yes | Brokerage street address. See nested fields. | |
| `ratings.average` | number | Yes | Profile rating average. | `5` |
| `ratings.count` | integer | Yes | Profile rating count. | `219` |
| `isTopAgent` | boolean | Yes | Profile top-agent flag. | `true` |
| `encodedZuid` | string | Yes | Same Zillow user id as the directory row when both are present. | `X1-ZUzl3bfxwglz49_47pep` |

#### `phoneNumbers` and `businessAddress`

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `phoneNumbers.cell` | string | Yes | Cell phone as published, including punctuation. | `(907) 343-8900` |
| `phoneNumbers.brokerage` | string | Yes | Brokerage phone as published. | `(907) 343-8900` |
| `phoneNumbers.business` | string | Yes | Business phone as published. | `(907) 274-0000` |
| `businessAddress.address1` | string | Yes | Street line. | `1557 C St., Suite 204` |
| `businessAddress.address2` | string | Yes | Second address line. | `null` |
| `businessAddress.city` | string | Yes | City. | `Anchorage` |
| `businessAddress.state` | string | Yes | State abbreviation on the profile. | `AK` |
| `businessAddress.postalCode` | string | Yes | Postal code. | `99501` |

#### `professionalInformation[]`

Each item is a labeled contact or credential block from the profile. The useful lead rows are cell phone, broker phone, websites, and licenses.

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `term` | string | Yes | Block label. | `Cell phone` |
| `description` | string | Yes | Single-line value, used for phone numbers. | `(907) 343-8900` |
| `lines` | array of string | Yes | Multi-line value, used for the broker address and license numbers. | `500063 (AK)` |
| `links` | array | Yes | Website and social links when `term` is `Websites`. | |
| `links[].text` | string | Yes | Link label. | `Website` |
| `links[].url` | string | Yes | Link URL. | `http://www.EveryAlaskaHome.com` |

#### `getToKnowMe`, licenses, and service areas

| Field | Type | Nullable | Description | Example |
|---|---|---:|---|---|
| `getToKnowMe.websiteUrl` | string | Yes | Website URL. | `http://www.EveryAlaskaHome.com` |
| `getToKnowMe.facebookUrl` | string | Yes | Facebook URL. | `https://www.facebook.com/RoyBrileyRealEstate/` |
| `getToKnowMe.instagramUrl` | string | Yes | Instagram URL. | `https://www.instagram.com/roybrileyregroup/` |
| `getToKnowMe.linkedInUrl` | string | Yes | LinkedIn URL. | `https://www.linkedin.com/feed/` |
| `getToKnowMe.yearsInIndustry` | integer | Yes | Years in the industry reported by the source. | `36` |
| `getToKnowMe.specialties` | array of string | Yes | Specialty labels. | `Buyer's Agent` |
| `getToKnowMe.languages` | array of string | Yes | Languages. An empty array has been observed. | `Spanish` |
| `getToKnowMe.description` | string | Yes | Profile biography text. | |
| `agentLicenses[].text` | string | Yes | License number. | `500063` |
| `agentLicenses[].state` | string | Yes | License state abbreviation. | `AK` |
| `agentLicenses[].status` | string | Yes | License status from the source. | `pending` |
| `agentLicenses[].license_type` | string | Yes | License type. | `agent` |
| `agentLicenses[].expiration` | string | Yes | Expiration date, `YYYY-MM-DD`. | `2028-01-31` |
| `otherLicenses[].licenseCode` | string | Yes | Other license code. | `15309` |
| `otherLicenses[].licenseDesc` | string | Yes | Other license description. | `Real Estate license` |
| `serviceAreas[].text` | string | Yes | Service-area label. | `Anchorage, AK` |
| `serviceAreas[].regionId` | integer | Yes | Source region id. | `23482` |
| `serviceAreas[].url` | string | Yes | Source path for the area. | `/anchorage-ak/` |

A successful `detailedProfile` also includes `forSaleListings`, `forRentListings`, `pastSales`, `reviewsData`, `teamDisplayInformation`, `mlsIDs`, and page metadata such as `breadcrumbs` and `currentUrl`. Those objects are source payloads. Listing price is a number in USD on observed for-sale rows. Review text is source text.

Free-plan agent records add `_trial` (`true`) and `_upgrade_url`. The extra upgrade item has `_type` `upgrade_cta`, `message`, and `recordsReturned`.

### Example dataset record

The record below is a real directory row for zip `99501` with the contact portion of its detailed profile. `getToKnowMe.description` and the listing, review, past-sale, team, and page-metadata objects are omitted here. They are present on the full enriched record.

```json
{
  "cardTitle": "Roy Briley Real Estate Group",
  "cardActionLink": "https://www.zillow.com/profile/Roy%20Briley%20RE%20Group",
  "encodedZuid": "X1-ZUzl3bfxwglz49_47pep",
  "imageUrl": "https://photos.zillowstatic.com/fp/f1ca7d45cacd64fa44e69e15450b6d11-h_l.jpg",
  "logoUrl": null,
  "isTopAgent": true,
  "secondaryCardTitle": "Real Estate Brokers of Alaska",
  "reviewInformation": {
    "noReviewsText": "No reviews",
    "reviewAverage": 5,
    "reviewAverageText": "5.0",
    "reviewCountFormattedText": "(219)"
  },
  "profileData": [
    {"formattedData": "$72K - $2M", "label": "team price range"},
    {"formattedData": "206", "label": "team sales last 12 months"},
    {"formattedData": "144", "label": "team sales in 99501"}
  ],
  "tags": [{"tagType": "WARNING", "text": "TEAM"}],
  "state": "Alaska",
  "city": "Anchorage",
  "zip_code": "99501",
  "page": 1,
  "hasDetailedProfile": true,
  "detailedProfile": {
    "displayUser": {
      "name": "Roy Briley Real Estate Group",
      "screenName": "Roy Briley RE Group",
      "businessName": "Real Estate Brokers of Alaska",
      "email": "rbreg@akreba.com",
      "phoneNumbers": {
        "cell": "(907) 343-8900",
        "brokerage": "(907) 343-8900",
        "business": "(907) 274-0000"
      },
      "businessAddress": {
        "address1": "1557 C St., Suite 204",
        "address2": null,
        "city": "Anchorage",
        "state": "AK",
        "postalCode": "99501"
      }
    },
    "professionalInformation": [
      {
        "term": "Cell phone",
        "description": "(907) 343-8900"
      },
      {
        "term": "Websites",
        "links": [
          {"text": "Website", "url": "http://www.EveryAlaskaHome.com"},
          {"text": "Facebook", "url": "https://www.facebook.com/RoyBrileyRealEstate/"}
        ]
      }
    ],
    "agentLicenses": [
      {
        "text": "500063",
        "state": "AK",
        "status": "pending",
        "license_type": "agent",
        "expiration": "2028-01-31"
      }
    ],
    "serviceAreas": [
      {"regionId": 23482, "text": "Anchorage, AK", "url": "/anchorage-ak/"},
      {"regionId": 36906, "text": "Palmer, AK", "url": "/palmer-ak/"}
    ]
  }
}
```

This row came from a zip query for `99501` with detailed profiles enabled. The same profile also published Instagram and LinkedIn under `Websites`, `getToKnowMe.websiteUrl` `http://www.EveryAlaskaHome.com`, and eight service areas. The example keeps two website links and two service areas.

### Query and input reference

| Input | Type | Required | Default | Accepted values | Description |
|---|---|---:|---|---|---|
| `zipCodes` | array of string | Conditional | none | Five-digit zip codes in the location index | Agents for those zip codes. One of `zipCodes`, `cities`, or `states` is required. |
| `cities` | array of string | Conditional | none | `State, City`, or a city name at 98% similarity | City lookup. City-only names can match more than one index key. |
| `states` | array of string | Conditional | none | Full state names in the input list | Every indexed city in the state. Alabama is listed and is not in the index. |
| `maxItems` | integer | No | `0` | Integer `0` or greater | Maximum unique agents. `0` means no cap, except the free plan, which returns 2. |
| `includeDetailedProfile` | boolean | No | `false` | `true` or `false` | Fetch profile contact fields. Charged as `detailed-data` when the page loads. Forced off on the free plan. |
| `maxConcurrency` | integer | No | `10` | Integer `1`–`50` | Concurrent profile fetches when detailed profiles are enabled. Values below 1 are raised to 1. |
| `proxyConfiguration` | object | No | Apify Residential proxy | Apify proxy object | Used for profile fetches when detailed profiles are enabled. |

Minimal directory request:

```json
{
  "zipCodes": ["99501"],
  "maxItems": 20
}
```

Contact-list request. Phone, email, website, and brokerage address are requested with `includeDetailedProfile`:

```json
{
  "zipCodes": ["99501"],
  "includeDetailedProfile": true,
  "maxItems": 20,
  "maxConcurrency": 10
}
```

### Retrieve the data through the API

1. Start `datascrapers/zillow-agents-scraper` with a JSON input.
2. Wait until the run finishes, or poll the run.
3. Read items from the run’s default dataset.
4. Use dataset `offset` and `limit`, or an Apify export format, for a larger contact list.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("datascrapers/zillow-agents-scraper").call(run_input={
    "zipCodes": ["99501"],
    "includeDetailedProfile": True,
    "maxItems": 20,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    user = (item.get("detailedProfile") or {}).get("displayUser") or {}
    phones = user.get("phoneNumbers") or {}
    print(item.get("cardTitle"), phones.get("cell"), user.get("email"))
```

Other languages are listed on the Actor’s API tab. Do not put a real token in a URL or in the input. This is the Apify Actor API. It is not a Zillow API.

### Data quality and record handling

The Actor deduplicates by `cardActionLink` inside a single run. Use that URL as the external unique key when you merge zip, city, and state runs. `encodedZuid` is the stable Zillow user id when you join this dataset to another Zillow record.

Directory text is stored as returned. Sales counts in `profileData` stay display strings. Phone numbers stay display strings. The Actor does not validate that a phone or email is current, and it does not add a phone or email that the profile page does not publish.

`detailedProfile` is the raw profile payload plus the directory fields. A failed profile fetch keeps the directory row, sets `hasDetailedProfile` to `false`, and charges `dataset-item` instead of `detailed-data`. A directory run never sets `hasDetailedProfile`.

An unknown zip, city, or state fails the run before records are useful as a complete territory. Overlapping locations in one run still collapse to one row per profile URL.

Run statistics are written to the key `run-stats`: `recordsScraped`, `recordsDetailed`, `recordsBasicFallback`, `runStartedAt`, `runFinishedAt`, `maxItems`, `includeDetailedProfile`, and `userTier`. Timestamps are UTC ISO 8601.

### Export and pipeline examples

| Destination | Recommended method | Typical use |
|---|---|---|
| CRM or outreach tool | CSV or Excel export of `cardTitle`, `phoneNumbers.cell`, `email`, and `businessName` | A call and email list for one zip or city |
| Google Sheets | Apify integration | Share a territory contact sheet |
| PostgreSQL or Supabase | Dataset API or a webhook consumer | Store agents and update them by `cardActionLink` |
| JSON pipeline | Dataset API `iterate_items` | Keep the nested phone, license, and service-area objects |

Flatten `detailedProfile.displayUser` before a CSV import if the destination cannot store nested objects. Excel and CSV exports of nested objects are JSON text inside the cell.

### Pricing and cost examples

Billing is pay per event, starting October 24, 2026. The user does not pay Apify platform usage costs.

A directory row charges `dataset-item`. A profile page that loads charges `detailed-data` instead of `dataset-item`. A profile fetch that fails charges `dataset-item`.

| Event | No discount | Bronze | Silver | Gold |
|---|---:|---:|---:|---:|
| `dataset-item` | $1.50 / 1,000 | $1.40 / 1,000 | $1.30 / 1,000 | $1.20 / 1,000 |
| `detailed-data` | $2.00 / 1,000 | $1.90 / 1,000 | $1.80 / 1,000 | $1.70 / 1,000 |

| Records | Events | Estimated cost, no discount |
|---:|---|---:|
| 1,000 directory agents | `dataset-item` | $1.50 |
| 10,000 directory agents | `dataset-item` | $15.00 |
| 1,000 agents with a loaded profile | `detailed-data` | $2.00 |
| 1,000 requested profiles, 900 loaded and 100 failed | 900 `detailed-data` and 100 `dataset-item` | $1.95 |

Estimates use the no-discount price. Bronze, Silver, and Gold prices are in the table above. `maxItems` limits how many agents a run saves. A free-plan run saves at most 2 directory records and does not request detailed profiles.

### Limitations and responsible data use

Directory rows come from the Actor’s Zillow agent index. They are not a live search of Zillow on every run. Phone, email, website, brokerage address, and license fields are read from the public profile page during the run, and only when detailed profiles are enabled.

The index covers 33,403 zip codes and 49 states. It does not include Alabama. A zip or city missing from the index fails the run. Contact fields can be missing when Zillow omits them. The Actor does not confirm that a number or email inbox is active.

Each run returns the index rows and, when requested, the profile pages available during that run. The Actor does not keep historical snapshots. Store the dataset yourself if you need a contact list as of a date.

You are responsible for complying with Zillow’s terms, privacy rules, and applicable law, including how you store agent contact details and how you use them for outreach.

### Dataset questions

#### What does one dataset item represent?

One Zillow real estate agent. With `includeDetailedProfile` enabled and a successful page load, that same item also carries phone, email, brokerage address, website, licenses, and service areas.

#### Which field should I use as a unique identifier?

Use `cardActionLink`. Use `encodedZuid` when you need the Zillow user id. The Actor already removes duplicate profile URLs inside one run.

#### Where are the phone number and email?

On an enriched record, use `detailedProfile.displayUser.phoneNumbers.cell`, `phoneNumbers.brokerage`, `phoneNumbers.business`, and `detailedProfile.displayUser.email`. The same phone numbers are repeated under `detailedProfile.professionalInformation` with terms `Cell phone` and `Broker phone`. A directory-only run does not include these fields.

#### Are contact fields nullable or conditional?

Yes. They exist only after a successful detailed-profile fetch. Email, each phone field, website, and address lines can still be null when the profile omits them. `languages` can be an empty array. `logoUrl` and `secondaryCardTitle` are nullable on the directory card.

#### Can I retrieve the contact list as CSV or JSON?

Yes. Export the run dataset as JSON, CSV, Excel, XML, or another Apify dataset format. JSON keeps nested phone and license objects. Flatten `displayUser` before loading a spreadsheet into a CRM.

#### How do I paginate a large agent list?

Limit a run with `maxItems`. Read a saved dataset with the Dataset API `offset` and `limit` parameters, or download an export. State and city queries can return a large index, so set `maxItems` when you want a sample contact list.

#### Does the Actor return historical contact data?

No. Directory rows come from the current location index, and profile contact fields come from the profile page at request time.

#### What counts as a billable result?

Each saved directory agent charges `dataset-item` at $1.50 per 1,000 before plan discounts. Each loaded profile charges `detailed-data` at $2.00 per 1,000 instead. A failed profile fetch stays on `dataset-item`. The user does not pay Apify platform usage costs. The free plan returns at most 2 directory records.

### Related datasets from Data Scrapers

- [Realtor.com Scraper](https://apify.com/datascrapers/realtor-scraper) — US home listing records you can place next to the agents who cover the same market.
- [Redfin Scraper](https://apify.com/datascrapers/redfin-scraper) — US listing records queried by zip code, aligned with `zip_code` on these agent rows.
- [Apartments.com Scraper](https://apify.com/datascrapers/apartments-scraper) — rental listing records, including property contact information, for the same city.
- [Crexi Scraper](https://apify.com/datascrapers/crexi-scraper) — commercial listing records for sale and lease when the outreach list includes commercial agents.
- [Yelp Scraper](https://apify.com/datascrapers/yelp-scraper) — local business records with phone numbers for the same city as the agent list.

### Data Scrapers support

Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.

# Actor input Schema

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

Five-digit US zip codes to extract agents for (e.g. "99546").

## `cities` (type: `array`):

For best results use "State, City" format (e.g. "Alaska, Adak"). City-only names are matched fuzzily at 98% similarity.

## `states` (type: `array`):

Select one or more states to extract all agents within. Leave empty if using zip codes or cities instead.

## `maxItems` (type: `integer`):

Maximum number of unique agents to return (0 = unlimited). Duplicates are removed automatically.

## `includeDetailedProfile` (type: `boolean`):

When enabled, fetches full agent profiles (contact info, licenses, listings, reviews, sales history). Billed separately per enriched record.

## `maxConcurrency` (type: `integer`):

Maximum concurrent profile fetches when detailed profiles are enabled.

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

Proxy settings for profile enrichment requests.

## Actor input object example

```json
{
  "zipCodes": [
    "72076"
  ],
  "states": [],
  "maxItems": 0,
  "includeDetailedProfile": false,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `agents` (type: `string`):

Dataset containing Zillow agent records

## `runStats` (type: `string`):

Run statistics including record counts and timestamps

# 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": [
        "72076"
    ],
    "states": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/zillow-agents-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": ["72076"],
    "states": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("datascrapers/zillow-agents-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": [
    "72076"
  ],
  "states": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datascrapers/zillow-agents-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascrapers/zillow-agents-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/qGyanIfkzfR1n686Z/builds/aq1m7YgDktcyAzjVL/openapi.json
