Zillow Agents Scraper
Pricing
from $1.20 / 1,000 dataset items
Zillow Agents Scraper
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.
Pricing
from $1.20 / 1,000 dataset items
Rating
0.0
(0)
Developer
Data Scrapers
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
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.
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.
{"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:
{"zipCodes": ["99501"],"maxItems": 20}
Contact-list request. Phone, email, website, and brokerage address are requested with includeDetailedProfile:
{"zipCodes": ["99501"],"includeDetailedProfile": true,"maxItems": 20,"maxConcurrency": 10}
Retrieve the data through the API
- Start
datascrapers/zillow-agents-scraperwith a JSON input. - Wait until the run finishes, or poll the run.
- Read items from the run’s default dataset.
- Use dataset
offsetandlimit, or an Apify export format, for a larger contact list.
from apify_client import ApifyClientclient = 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 — US home listing records you can place next to the agents who cover the same market.
- Redfin Scraper — US listing records queried by zip code, aligned with
zip_codeon these agent rows. - Apartments.com Scraper — rental listing records, including property contact information, for the same city.
- Crexi Scraper — commercial listing records for sale and lease when the outreach list includes commercial agents.
- 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.
