Coldwell Banker Scraper [$2/1K๐ฐ] | Listings, Agents & Offices
Pricing
from $1.90 / 1,000 listings
Coldwell Banker Scraper [$2/1K๐ฐ] | Listings, Agents & Offices
Pull US property listings, listing-agent contact details and office/agent directories from Coldwell Banker into three separate datasets - price, beds, sqft, lot, taxes, open houses, MLS data, plus agent and office rosters.
Pricing
from $1.90 / 1,000 listings
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
24 days ago
Last modified
Categories
Features
Share
Coldwell Banker Scraper
Pull US property listings, listing-agent contact details and full office/agent directories from coldwellbanker.com into three separate datasets โ 75 listing fields, 26 agent fields, 27 office fields, including price, beds, sqft, lot size, open-house schedules, MLS attribution and every agent's email and phone.
Built for real-estate investors, proptech data teams, mortgage and insurance lead-gen, and agent recruiters.
Before you publish or resell anything: Coldwell Banker listing data is MLS-derived. That carries redistribution restrictions independent of this Actor. Read Legal & Compliance first.
What you get
A whole-city price snapshot for one request per 32 listings
This is the thing that makes large runs affordable. Alongside normal listing rows, the Actor emits listingSummary rows โ one per city-search page, each holding a listings[] array of cheap search hits (price, beds, baths, sqft, type, MLS, status, lat/lng, first photo), plus total, the number of matching listings city-wide.
Those summary rows are not billed. A 1,000-listing market costs about 32 requests for the whole city, not 1,000.
Listing detail rich enough for valuation models
price, originalPrice, bathsDecimal, sqft, lotSizeSqft, lotSizeAcres, lotDimensions, yearBuilt, garageSpaces, parkingSpaces, stories, architecturalStyle, flooring, heating, basement, hasFireplace, isNewConstruction, daysOnMarket and listingContractDate โ the fields a comps or pricing model actually needs, all in one row.
Open-house schedules as structured data
openHouses[] carries date, startTime, endTime, byAppointment and showOnInternet per event, plus a hasOpenHouse boolean. That is the field for agent-scheduling and open-house lead-gen, and you can filter for it server-side with the hasOpenHouses input instead of filtering 1,000 rows yourself.
Listing-agent contact details with honest coverage
listingAgentName, listingAgentPhone, listingAgentEmail, listingAgentMlsId, coListingAgentName, coListingAgentPhone, officeName, officePhone, officeMlsId. Agent phone is MLS-dependent โ see Why is listingAgentPhone sometimes null? before you rely on it.
Agent and office rosters nobody derives from listings
A listing page's embedded payload never links to an agent or office profile, so agents and offices are not obtainable from a listing search. This Actor takes them directly: 26 agent fields (bio, specialties, languages, activeListingsCount, soldListingsCount, email, phone) and 27 office fields (totalAgents, areasServed[], agentsServed, agents[], totalStaff), via seed URLs or bulk sitemap discovery.
How it works
coldwellbanker.com is a Next.js application. Every route server-renders its entire dataset for that route into a single inline script tag:
<script id="__NEXT_DATA__" type="application/json">{ โฆ pageProps โฆ }</script>
So the Actor downloads plain HTML with CheerioCrawler โ plain HTTP, no JavaScript execution โ and JSON.parses that blob. Consequences:
- No browser. Roughly 10ร cheaper than a Playwright run and about 10ร faster, because there is no browser boot and no client-side render wait.
- No anti-bot to bypass. There is no Cloudflare, Turnstile, DataDome or fingerprint challenge to work around, because the data is already in the first HTTP response.
| Purpose | URL | Data used |
|---|---|---|
| City listing search | /city/{state}/{city} | propertiesData.properties[] (32/page), .total, .paginationMetadata |
| Property detail | /{state}/{city}/{address}/lid-{id} | pageProps.propertyDetails + rawPropertyDetails |
| Agent profile | /{state}/{city}/agents/{name}/aid-{id} | pageProps.detail.agentDetails |
| Office directory | /{state}/{city}/offices/{slug}/oid-{id} | pageProps.detail |
| Listing sitemaps | /xml-sitemap/states/sitemapindex-listings.xml | <loc> โ 2,267 per-state sitemaps |
| Agent sitemaps | /xml-sitemap/states/sitemapindex-agents.xml | <loc> |
| Office sitemaps | /xml-sitemap/states/sitemapindex-offices.xml | <loc> |
Every one of those sitemaps is declared in robots.txt, which for User-agent: * contains no Disallow rules at all โ only those six Sitemap: lines.
Search filters all apply server-side: minPrice, maxPrice, minBedrooms, maxBedrooms, minBathrooms, minSqft, maxSqft, propertyType (SFR, CONDO, COOP, TOWNHOUSE, MFR, MFD, LAND, FARM), status (ACTIVE, PENDING, COMING_SOON, โฆ), hasOpenHouses, isRental, isNewConstruction, sortBy, keyword, page.
Why sitemap discovery is budgeted per kind
Bulk enumeration is where scrapers usually cannibalise themselves. Here each child sitemap queues at most maxListings/maxAgents/maxOffices URLs minus what has already been collected, so listing discovery can never drain the request budget and starve agent or office collection. Search results seeded from searchLocations always process first, and listing detail pages are dequeued with forefront, so bulk discovery never delays your primary output.
Stale search entries don't eat your quota
City search indexes occasionally list properties whose detail page 404s (the page renders listingNotFoundContent and carries no payload). The Actor detects this, logs Listing not found (stale search entry), and backfills the slot from the rest of the same search page โ so a dead entry never consumes maxListings. Expect roughly 1 stale hit per 15โ30 listings on fast-moving markets.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
searchLocations | string[] | ["ny/new-york"] | City slugs in the form "<state>/<city>", e.g. ny/new-york, ca/san-francisco. |
startUrls | string[] | [] | Direct listing, agent or office URLs. Route is auto-detected. |
includeDetails | boolean | true | Expand each search hit to a detail request for the full 75-field row. |
minPrice / maxPrice | integer | โ | Price range, applied server-side. |
minBedrooms / maxBedrooms | integer | โ | Bedroom range. |
minBathrooms | integer | โ | Minimum bathrooms. |
minSqft / maxSqft | integer | โ | Living-area range. |
propertyType | string[] | โ | Any of SFR, CONDO, COOP, TOWNHOUSE, MFR, MFD, LAND, FARM. |
status | string[] | โ | Any of ACTIVE, PENDING, COMING_SOON, โฆ |
hasOpenHouses | boolean | โ | Only listings with a published open-home schedule. |
isRental / isNewConstruction | boolean | โ | Boolean filters. |
sortBy | string | โ | newest, price_asc, price_desc, living_area_desc. |
keyword | string | โ | Free-text keyword pass-through. |
maxListings | integer | 50 | Hard cap on listing records. |
maxPagesPerLocation | integer | 2 | 32 listings per page. |
sitemapDiscovery | object | { enabled: false, states: [], kinds: ["listings"], maxUrls: 100 } | Bulk-enumerate from XML sitemaps. kinds: listings, agents, offices. |
maxAgents | integer | 20 | Cap on agent records. |
maxOffices | integer | 20 | Cap on office records. |
maxRequestsPerCrawl | integer | 300 | Runaway guard. |
proxy | object | { useApifyProxy: false } | Standard Apify proxy picker. |
Agents and offices need their own source
searchLocations alone will always yield agents: 0, offices: 0, because a listing page's payload never links to an agent or office profile. Use one of:
- put agent/office URLs (or a whole directory URL) in
startUrlsโ the router detects the route; - or set
sitemapDiscovery: { enabled: true, kinds: ["agents","offices"], states: ["ny"] }.
If you set maxAgents/maxOffices without a source, the Actor logs an explicit warning rather than silently returning nothing.
Output
Three datasets, so each record type validates, exports and bills independently.
| Dataset | Alias | Contents |
|---|---|---|
| Listings | default | listing, listingSummary |
| Agents | agents | agent |
| Offices | offices | office |
Run totals are not a dataset record โ they go to the key-value store as RUN_SUMMARY.json (listings, agents, offices, billed, sitemapUrlsQueued, pagesFetched, isPaying, finishedAt, aborted), so a summary row is never billed as data.
Listings (default) โ 75 fields
type, listingId, mlsNumber, mlsSource, mlsName, url, price, originalPrice, currency, priceText, isPriceHidden, isSoldListing, address, city, state, stateName, zip, county, fullAddress, latitude, longitude, neighborhood, beds, baths, bathsDecimal, bathsFull, sqft, lotSizeSqft, lotSizeAcres, lotDimensions, yearBuilt, garageSpaces, parkingSpaces, stories, architecturalStyle, flooring, heating, basement, hasFireplace, propertyType, isNewConstruction, isRental, description, photos, photoCount, openHouses, hasOpenHouse, listingAgentName, listingAgentPhone, listingAgentEmail, listingAgentMlsId, coListingAgentName, coListingAgentPhone, officeName, officePhone, officeMlsId, status, displayStatus, isComingSoon, isVirtualTourAvailable, listingContractDate, firstAppearedDate, daysOnMarket, lastUpdated, mlsDisclaimer, idxFeedAttributionCompany, source, detailFetched, scrapedAt, location, searchUrl, placeMasterId, page, total, listings
Views: Overview, Details, Search pages.
Agents (agents) โ 26 fields
type, agentId, name, firstName, lastName, email, phone, photo, bio, specialties, languages, officeName, officeId, officeUrl, officePhone, address, city, state, stateName, zip, latitude, longitude, activeListingsCount, soldListingsCount, url, source
Views: Overview, Profiles.
Offices (offices) โ 27 fields
type, officeId, name, companyName, brandCode, phone, email, website, address, addressLine2, city, state, zip, country, latitude, longitude, photo, logo, areasServed, totalAgents, totalStaff, agentsServed, agents, activeListingsCount, soldListingsCount, url, source
Views: Overview, Directories, Agent roster.
Field notes that change how you read the data:
typeis your record discriminator:listing,listingSummary,agentoroffice. Filter on it before loading to a warehouse.sqftfalls back throughstructure.livingAreaโbuildingAreaTotalโ the SSR display string. Land, farm and vacant listings legitimately have none, sonullis normal.openHousesis[]unless the MLS published a schedule. That is an empty schedule, not a missing field.officeName/officePhoneon a listing come from the MLS attribution block, so they name the listing brokerage โ often an independent franchise, not Coldwell Banker. Usetype: "office"rows for true CB office directories.- Agent source matters: a directory page (
/city/{state}/{city}/agents, 12 agents per request) gives name, email, phone, photo, office and URL; a profile page addsbio,specialties,languages,activeListingsCountandsoldListingsCount. Directory rows leave the profile-only fieldsnull. Seed profile URLs when you need the extras.
Example input
City search with filters:
{"searchLocations": ["ny/new-york"],"propertyType": ["SFR"],"minBedrooms": 3,"maxPrice": 2500000,"status": ["ACTIVE"],"maxPagesPerLocation": 3,"maxListings": 100}
Cheap whole-city price snapshot โ no detail requests, summary rows only:
{"searchLocations": ["ca/san-francisco", "ny/brooklyn"],"includeDetails": false,"maxPagesPerLocation": 10,"maxListings": 2000}
Agent roster for recruiting:
{"searchLocations": [],"sitemapDiscovery": { "enabled": true, "states": ["ny"], "kinds": ["agents"], "maxUrls": 300 },"maxAgents": 300,"maxRequestsPerCrawl": 400}
Specific listing, agent and office pages:
{"searchLocations": [],"startUrls": ["https://www.coldwellbanker.com/ny/springfield-gardens/21626-131st-ave/lid-P00800000HI8DebheIrz6ty0mDIFY6RivDTTN4Mm","https://www.coldwellbanker.com/ny/brooklyn/agents/anthony-marra/aid-P00200000FDdqmuwdqxLZyHkaMD67yyZH1zRejeU"]}
Example output
{"type": "listing","listingId": "P00800000HI8DebheIrz6ty0mDIFY6RivDTTN4Mm","mlsNumber": "1234567890","mlsSource": "onekey","mlsName": "OneKey MLS","url": "https://www.coldwellbanker.com/ny/springfield-gardens/21626-131st-ave/lid-P00800000HI8DebheIrz6ty0mDIFY6RivDTTN4Mm","price": 685000,"originalPrice": 725000,"currency": "USD","priceText": "$685,000","isPriceHidden": false,"isSoldListing": false,"address": "21626 131st Ave","city": "Springfield Gardens","state": "NY","stateName": "New York","zip": "11012","county": "Queens","fullAddress": "21626 131st Ave, Springfield Gardens, NY 11012","latitude": 40.65412,"longitude": -73.74431,"neighborhood": "Springfield Gardens","beds": 4,"baths": 3,"bathsDecimal": 2.5,"bathsFull": "2.5","sqft": 2340,"lotSizeSqft": 4800,"lotSizeAcres": 0.1101,"lotDimensions": "60x80","yearBuilt": 1954,"garageSpaces": 1,"parkingSpaces": 1,"stories": 2,"architecturalStyle": "Cape Cod","flooring": "Hardwood","heating": "Forced Air","basement": "Full","hasFireplace": true,"propertyType": "SFR","isNewConstruction": false,"isRental": false,"description": "Well-maintained Cape Cod on a quiet block, finished basement, updated roof 2021.","photos": ["https://imagecache.coldwellbanker.com/1234567890/photo-01.jpg"],"photoCount": 28,"openHouses": [{ "date": "2026-10-11", "startTime": "12:00 PM", "endTime": "02:00 PM", "byAppointment": false, "showOnInternet": true }],"hasOpenHouse": true,"listingAgentName": "Anthony Marra","listingAgentPhone": null,"listingAgentEmail": "anthony.marra@cbrealty.com","listingAgentMlsId": "P00200000FDdqmuwdqxLZyHkaMD67yyZH1zRejeU","coListingAgentName": null,"coListingAgentPhone": null,"officeName": "Marra Realty Group","officePhone": "(718) 555-0132","officeMlsId": "OFF-7781","status": "ACTIVE","displayStatus": "Active","isComingSoon": false,"isVirtualTourAvailable": true,"listingContractDate": "2026-09-18","firstAppearedDate": "2026-09-19","daysOnMarket": 21,"lastUpdated": "2026-10-04T06:12:00.000Z","mlsDisclaimer": "The data is deemed reliable but is not guaranteed.","idxFeedAttributionCompany": "OneKey MLS","source": "search","detailFetched": true,"scrapedAt": "2026-10-04T06:12:41.220Z"}
Integrations & automation
Call it over the Apify API (POST /v2/acts/1cOxtsUkKezlOoke4/runs), or from Python, JavaScript, the CLI or MCP. All three datasets export as JSON, CSV, Excel, XML or RSS.
For market monitoring, includeDetails: false plus a weekly schedule over a list of searchLocations gives you city-level price and inventory movement cheaply โ the listingSummary rows are unbilled, so this is the cheap path. For agent lead-gen, run sitemap discovery per state monthly and upsert on agentId; agent rosters change slowly.
Typical pipeline: run on schedule โ split datasets on type โ upsert listings on listingId and agents on agentId โ alert when a tracked mlsNumber goes ACTIVE โ PENDING, when daysOnMarket passes a threshold, or when a tracked neighbourhood's median price/sqft moves more than ~5%. PostGIS works directly: latitude/longitude are on listings, agents and offices.
What a run costs
| Configuration | Events | Cost |
|---|---|---|
City snapshot, includeDetails: false, 3 pages | summary rows only โ unbilled | $0 |
| 50 listing detail rows | 50 ร listing | $0.10 |
| 300 agent rows | 300 ร agent | $1.80 |
| 200 office rows | 200 ร office | $1.00 |
Free accounts get a 10-listing preview; paying accounts get the full maxListings. listingSummary rows are never charged โ one row is a whole page of results, not a single listing.
Related Actors
| Actor | Why |
|---|---|
century21-scraper | The same problem on the other big US brokerage brand โ the closest structural comparison in this portfolio. |
cargurus-scraper | US vehicle-marketplace listings with seller and vehicle detail data. |
cars-com-scraper | Same US-marketplace shape, different vertical โ useful for schema and price-comparison patterns. |
housinganywhere-scraper | Long-term rental listings in the UK and Europe, for geographic expansion. |
wallapop-scraper | Marketplace listings in Spain, with the same listing-detail + seller structure. |
FAQ
Why not use the official Coldwell Banker API?
Because there isn't a usable one for this data. Coldwell Banker is built on an internal real-estate platform (api.anywhere.re) whose public runtime config leaks an API key and a /properties route, but that key is scoped and rotated โ calling it directly returns 401 {"statusCode":401,"message":"Invalid ApiKey for given resource"}. What that internal endpoint would give you is the same data already present in the server-rendered page. So the Actor reads the server-rendered JSON instead: no key, no auth, more robust.
Agents and offices come back as zero. Why?
Because a listing page's payload never links to an agent or office profile, so a listing search cannot produce them. Supply agent or office URLs in startUrls, or enable sitemapDiscovery with kinds: ["agents","offices"]. Setting maxAgents/maxOffices without a source logs an explicit warning rather than silently returning nothing.
Why is listingAgentPhone sometimes null?
It is MLS-dependent, and the Actor will not invent one. Midwestern feeds such as Midwest Real Estate Data (IL, WI) populate it; New York's OneKey MLS feed does not ship the field at all. Agent email and office phone are populated in both. If you need guaranteed agent phone numbers, scrape agent profile pages โ those always carry a business phone number.
Why do some listings have no sqft?
Because sqft is resolved through a fallback chain ending at the rendered display string, and land, farm and vacant listings genuinely have no living area. null is the correct value there, not a parse failure.
Why is officeName on a listing not "Coldwell Banker"?
Because it comes from the MLS attribution block, so it names the brokerage that actually holds the listing โ frequently an independent franchise. For true CB office directories, read the offices dataset instead.
Why am I getting fewer listings than maxListings?
Three causes, all normal: New York's OneKey index limits how many listings a city search returns; maxPagesPerLocation may be too low; and stale search entries whose detail page 404s are detected and skipped (with the slot backfilled where possible). Expect roughly 1 stale hit per 15โ30 listings on fast-moving markets โ the log line is Listing not found (stale search entry).
Do I need a browser or a proxy?
No. The data is in the first HTML response, so CheerioCrawler with plain HTTP is enough. There is no Cloudflare, DataDome, Akamai or fingerprint challenge on this target. Proxy defaults to off; enable it only if you plan high-volume runs.
SEO Keywords
coldwell banker scraper, coldwellbanker.com, us real estate listing data, real estate leads, listing agent contact data, property listing api, open house schedule data, mls listing data, house for sale data, realtor directory data, real estate agent directory, real estate office directory, proptech data pipeline, comps data, us property market research, real estate price monitoring, listing photos and details, property valuation data, agent lead generation, mortgage lead generation, real estate market analysis, bulk property scraping
For AI Agents & LLM Apps
Returns Coldwell Banker data as three flat datasets โ default (listings + page summaries), agents, offices โ discriminated by a type field.
Minimal input โ smallest input that produces a valid run:
{ "maxListings": 25 }
Cheapest useful run โ whole-city snapshot, no detail requests, summary rows are unbilled:
{ "searchLocations": ["ny/new-york"], "includeDetails": false, "maxPagesPerLocation": 5 }
Filtered listing search:
{ "searchLocations": ["ny/new-york"], "propertyType": ["SFR"], "minBedrooms": 3, "status": ["ACTIVE"], "maxListings": 100 }
Agent roster (requires sitemap discovery or agent URLs โ listings alone yield zero agents):
{ "searchLocations": [], "sitemapDiscovery": { "enabled": true, "states": ["ny"], "kinds": ["agents"] }, "maxAgents": 200 }
Output fields โ listings (75): type, listingId, mlsNumber, mlsSource, mlsName, url, price, originalPrice, currency, priceText, isPriceHidden, isSoldListing, address, city, state, stateName, zip, county, fullAddress, latitude, longitude, neighborhood, beds, baths, bathsDecimal, bathsFull, sqft, lotSizeSqft, lotSizeAcres, lotDimensions, yearBuilt, garageSpaces, parkingSpaces, stories, architecturalStyle, flooring, heating, basement, hasFireplace, propertyType, isNewConstruction, isRental, description, photos, photoCount, openHouses, hasOpenHouse, listingAgentName, listingAgentPhone, listingAgentEmail, listingAgentMlsId, coListingAgentName, coListingAgentPhone, officeName, officePhone, officeMlsId, status, displayStatus, isComingSoon, isVirtualTourAvailable, listingContractDate, firstAppearedDate, daysOnMarket, lastUpdated, mlsDisclaimer, idxFeedAttributionCompany, source, detailFetched, scrapedAt, location, searchUrl, placeMasterId, page, total, listings
Output fields โ agents (26): type, agentId, name, firstName, lastName, email, phone, photo, bio, specialties, languages, officeName, officeId, officeUrl, officePhone, address, city, state, stateName, zip, latitude, longitude, activeListingsCount, soldListingsCount, url, source
Output fields โ offices (27): type, officeId, name, companyName, brandCode, phone, email, website, address, addressLine2, city, state, zip, country, latitude, longitude, photo, logo, areasServed, totalAgents, totalStaff, agentsServed, agents, activeListingsCount, soldListingsCount, url, source
Behaviours an agent should know
- Three datasets, one
typefield. Always filter ontype(listing,listingSummary,agent,office) before processing โ thedefaultdataset mixes full listings with per-page summary rows. listingSummaryrows are not billed. Each holds alistings[]array plustotal(city-wide match count). This is the cheapest way to get market-level price data: one request per 32 listings.- Agents and offices require their own source.
searchLocationsalone always yieldsagents: 0, offices: 0. UsestartUrlswith agent/office URLs, orsitemapDiscovery.kinds: ["agents","offices"]. Otherwise the run logs an explicit warning. includeDetailsdefaults totrue. Setting itfalseskips detail pages entirely โ much cheaper, but you get only search-level fields.listingAgentPhoneis MLS-dependent and may benull(OneKey MLS does not ship it).listingAgentEmailandofficePhoneare reliable. Agent profile rows always have a phone.- Stale search entries (detail page 404s) are detected and skipped, and the slot is backfilled from the same page where possible โ so counts stay close to
maxListingswithout exceeding it. - Billing is per-event: $0.002 per listing, $0.006 per agent, $0.005 per office.
listingSummaryrows cost nothing. Agents are the most expensive record type by far โ check the tiered pricing table for paid-plan rates before scraping a full state roster. - Free accounts are capped at 10 listings;
maxAgents/maxOfficesare not plan-capped.
Legal & Compliance
This Actor is an independent third-party tool. It is not affiliated with, endorsed by, or sponsored by Coldwell Banker, by any Coldwell Banker franchisee, or by any MLS.
What it actually accesses: publicly visible Coldwell Banker listing, agent and office pages over plain HTTP, plus the XML sitemaps that robots.txt explicitly declares. No login, no authentication bypass, no captcha solving, no headless browser. robots.txt for User-agent: * contains no Disallow rules โ only Sitemap: declarations.
The real constraint is MLS data licensing, not robots.txt. Coldwell Banker listing data is sourced from regional Multiple Listing Services (this Actor surfaces mlsSource, mlsName, mlsDisclaimer and idxFeedAttributionCompany on every row precisely so you know whose data you are holding). MLS data is licensed to brokerages for member use. Redistribution, resale, republication or use in a competing data product is generally restricted by those agreements and by NAR rules, even where the web page is publicly viewable. If your use case is anything other than internal analysis of markets where you operate, get written clearance first โ this Actor's README is not that clearance.
Personal data. The agents dataset contains email and phone for real estate professionals, which are business contact details published for buyer enquiries. B2B outreach to agents is regulated in the US by CAN-SPAM (email) and TCPA (automated or prerecorded calls to mobile numbers). Note also that named agent consent is not implied by publication: claimedStatus is not exposed on agent rows, so verify before you treat a record as an opt-in contact. GDPR applies to agents with EU ties, and Canadian PIPEDA to agents in Canada.
Platform terms. Coldwell Banker's own Terms of Service and franchise agreements also bind, and individual franchises may set additional restrictions.
You are solely responsible for compliance with those agreements, Coldwell Banker's Terms of Service, robots.txt, and applicable law. Keep volumes modest: maxRequestsPerCrawl (default 300), maxConcurrency 3 and maxRequestRetries 3 bound a run without effort. Do not use this Actor to build or resell a competing property-listing data product without a licence.