Brownbook Scraper [From $2💰] | 44M+ Business Data
Pricing
from $1.90 / 1,000 results
Brownbook Scraper [From $2💰] | 44M+ Business Data
Scrape 44M+ global business listings from brownbook.net: name, address, phone, email, website, categories, hours, reviews, ratings, social links and claim status. Public sitemap tree and a challenge-free JSON API - no browser, no CAPTCHA.
Pricing
from $1.90 / 1,000 results
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
Brownbook Scraper — Scrape 44M+ Global Business Listings As brownbook.net Data
Scrape 44M+ global business listings from brownbook.net — names, addresses, phones, emails, websites, socials, categories, opening hours, photos, videos, reviews, ratings and claim status — as structured brownbook.net data you can export and schedule. Built for lead-gen agencies, citation-building services, business data aggregators and sales teams that need a B2B contact database without a ZoomInfo or D&B contract.
Main Use Cases For B2B Lead Lists And Local SEO Citation Data
- B2B lead list / sales intelligence data — one row per company with phone, mobile, email, website and socials, ready to qualify.
- NAP data for local SEO citation building —
name,address,phone,website,city/state/zipCode, plusclaimed,claimVerified,claimEndDateto find listings that still need claiming. - Global business database / business data aggregator feeds — the full 92-field record including NAICS business data (
naicsCode,naicsTitle,naicsBreadcrumb), categories, tags, services, payment options. - Company email phone database —
email,emails,additionalEmails,phone,mobile,voip,additionalPhones(see Legal on outreach). - CRM enrichment — pass known IDs to
businessIds, get one rich record back per ID, no crawling. - Change monitoring — schedule the highest leaf sitemaps (most recently updated listings) and diff
updatedAt/lastmod.
Build A Global Business Database Without Official API Access
brownbook.net is a Next.js site on Vercel behind Cloudflare. Its search UI is CAPTCHA-gated, but its sitemap tree and JSON API are not. This Actor enumerates IDs from the public sitemap tree — sitemap index → 31 index files → ~46,531 leaf sitemaps of 1,000 URLs each — then reads GET https://api.brownbook.net/app/api/v1/businesses/resource/<id> for the complete 92-field record as plain JSON. Extraction runs on CheerioCrawler: pure HTTP, no browser, no session pool, no cookies, no API key, no CAPTCHA solver. Reviews land in a second dataset, brownbookreviews. Endpoints, rejected alternatives and measured costs are below.
Input Parameters
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
sitemapIndex | string (select) | No | "1" | Index file "1"…"31"; each lists 1,501 leaf sitemaps (~1.5M businesses). Comma-separated lists work over the API ("2,3,4"). |
sitemapLeafCount | string (select) | No | "1" | Leaf sitemaps to expand; 1 leaf = 1,000 business URLs. Presets "1"…"1501" = 1,000 … 1,501,000 businesses. |
businessIds | string | No | "" | Comma/space-separated numeric IDs fetched in full, e.g. "53562541, 53562540". Skips discovery. |
startUrls | array | No | [] | Explicit leaf sitemaps (.../sitemap/50000.xml) or resource/<id> records instead of default discovery. |
countrySample | boolean | No | false | 30-row sample + total count per country from https://api.brownbook.net/businesses?country=<cc> (no pagination — coverage stats). |
countries | string | No | "us,gb,de,au,ca,fr" | Comma-separated ISO codes; only used in sample mode. |
detail | boolean | No | true | true = 92-field record per ID; false = sitemap IDs only (cheapest). |
includeMedia | boolean | No | true | Fetch photo/video URLs; +1 request per business. |
includeReviews | boolean | No | true | Write reviews to brownbookreviews (business rows keep rating + reviewCount). Embedded reviews free; possible extras cost up to 5 requests. |
maxReviewsPerBusiness | integer | No | 0 | Cap review rows per business — 0 = all, hard max 25 (5 pages × 5). Lowers Review charges and skips comments calls once hit. |
maxItems | integer | No | 5000 | Hard cap on business rows (1–250,000). Free accounts always capped at 50; review rows never consume this budget. |
proxy | object | No | { "useApifyProxy": false } | Standard Apify proxy picker; applies to sitemap, JSON API and enrichment requests. |
Legacy inputs still work:
sitemapLeavesis read assitemapIndexandmaxLeafSitemapsassitemapLeafCount.
Modes
| Mode | Trigger | Output |
|---|---|---|
| Sitemap (default) | sitemapIndex / sitemapLeafCount set | Full business records from the sitemap tree |
| By ID | businessIds set | One rich record per ID — best for enrichment |
| Start URLs | startUrls set | Whatever URLs you pass (leaf sitemaps or resource/<id>) |
| Country sample | countrySample: true | 30-row sample per country + totalFound counts |
| Taxonomy | nothing set | Country coverage, top categories, full category taxonomy |
Output Fields
| Dataset | Contains |
|---|---|
| default | Business records plus meta rows (run_summary, sitemap_index, …) |
brownbookreviews | One row per review (business rows keep only rating and reviewCount) |
The reviews dataset is an alias declared in .actor/actor.json (storages.datasets.brownbookreviews) and opened with Actor.openDataset({ alias }), so the platform creates it at run start with its own schema and the Reviews view and lists it in the run's Storage tab beside the default dataset (the Output tab carries a direct Reviews link). includeReviews: false leaves it untouched. Aliases allow letters, digits and underscores while dataset names reject underscores — hence lowercase brownbookreviews.
Default-dataset rows are tagged with type: business (full listing, fields below), business_sample (30-row country sample), country_coverage (per-country record counts), taxonomy (category/country taxonomies), sitemap_index (the discovered sitemap tree), business_url (sitemap IDs only, detail: false), run_summary (run configuration).
business fields
Identity & claim status — id, legacyBusinessId, name, shortName, slug, url, claimed, claimVerified, claimEndDate, approvedAt, businessProfileCompleted, profileCompleted, subscribed, userId, duplicateOf, closed, closedDate
Location — country, countryCode, state, city, area, address, addressLine1, addressLine2, addressLine3, addressExtra, zipCode, postcode, serviceArea, lat, lng
Contact — phone, mobile, voip, fax, email, emails, website, websites, websitesHost, additionalPhones, additionalWebsites, additionalEmails
Social links — socials (map), socialsPresent, facebook, twitter, instagram, linkedin, tiktok, youtube, skype, blog
Classification — categories, category, naicsCode, naicsTitle, naicsBreadcrumb, naicsConfidence, tags, services, products, specials, brands, associations, languages, paymentOptions, yearEstablished
Content & media — description, businessHours (day → intervals), hoursDisplay, specialOffers, logoUrl, imageCount, images, videoCount, videos, rating, reviewCount
Meta — createdAt, updatedAt, indexedAt, lastmod, scrapedAt, source
Meta rows and views
Non-business rows carry totalFound (per-country counts), indexCount (31), totalLeafSitemaps (~46,531), estimatedBusinessUrls (~46.5M), data (raw payload), mode (which of the five modes ran) and isPaying. Two views ship with the dataset: Businesses (name, city, countryCode, category, phone, email, website, claimed) and Contact leads (name, phone, mobile, email, website, facebook, instagram, linkedin, url).
brownbookreviews fields
type (review), reviewId, businessId, businessName, businessUrl, businessCountryCode, rating, comment, status, authorId, author, authorCountry, authorAvatar, mediaUrl, reply, createdAt, updatedAt, source, scrapedAt.
reviewId(notid):idis a reserved keyword when declared in a dataset schema — the platform rejects it withNOT SUPPORTED: keyword "id", use "$id".
Example Input And Output
First 5,000 US listings (5 leaf sitemaps): { "sitemapIndex": "1", "sitemapLeafCount": "5", "maxItems": 5000 }
Enrich specific businesses: { "businessIds": "53562541,53562540,53562539" }
Cheapest pass — IDs only, no detail calls: { "detail": false, "maxItems": 20 }
Targeted leaf sitemaps (recently-updated listings): { "startUrls": ["https://www.brownbook.net/sitemap/46000.xml"] }
Country coverage statistics: { "countrySample": true, "countries": "us,gb,de,au,ca,fr,de,it" }
A business row:
{"type": "business","id": 53562541,"name": "Riverside Dental Studio","url": "https://www.brownbook.net/business/53562541/riverside-dental-studio/","claimed": true,"claimVerified": true,"closed": false,"countryCode": "us","city": "Chicago","address": "1420 W Riverside Drive, Chicago, IL 60610","zipCode": "60610","lat": 41.9217,"lng": -87.6513,"phone": "+1 312 555 0142","email": "reception@riversidedental.example","website": "https://www.riversidedental.example","category": "Dentist","naicsCode": "621210","rating": 4.7,"reviewCount": 18,"lastmod": "2026-09-18T07:31:12Z","scrapedAt": "2026-10-07T09:14:22Z","source": "brownbook"}
A review row from brownbookreviews:
{"type": "review","reviewId": 88123456,"businessId": 53562541,"businessName": "Riverside Dental Studio","rating": 5,"comment": "Seen on time, friendly team, clear pricing.","author": "J. Moreno","createdAt": "2026-06-12T15:02:10Z","scrapedAt": "2026-10-07T09:14:22Z","source": "brownbook"}
Brownbook API Endpoints And The Sitemap Enumeration Strategy
Endpoints used
| Purpose | Endpoint |
|---|---|
| Sitemap index (root) | https://api.brownbook.net/sitemap_indexes.xml |
| Index files (31) | https://www.brownbook.net/sitemap/index_<n>.xml |
| Leaf sitemaps (~46,531) | https://www.brownbook.net/sitemap/<n>.xml — 1,000 URLs each |
| Business detail (the data source) | GET https://api.brownbook.net/app/api/v1/businesses/resource/<id> |
| Photos & videos | GET .../api/v1/businesses/resource/<id>/media |
| Reviews (paginated, 5 per page) | GET .../api/v1/business/<id>/comments?page=<n> |
| Country coverage + counts | GET .../api/v1/businesses/countries |
| Top countries | GET .../api/v1/businesses/countries/top |
| Top categories | GET .../api/v1/businesses/categories/top |
| Full category taxonomy | GET .../api/v1/uberall-categories |
| City autocomplete | GET .../api/v1/autocomplete/cities/?search=<q> |
| Country sample (30 rows) | GET https://api.brownbook.net/businesses?country=<cc> |
Why this strategy
- Embedded JSON blob → not viable. The homepage ships Next.js App Router RSC flight data (
self.__next_f.push) with only shell markup — no__NEXT_DATA__, noapplication/ld+json, no listing data. - Algolia / third-party search backend → none. No
algoliasearch(), Meilisearch, Elasticsearch, TypeSense or Coveo anywhere in the bundle. - Internal JSON API → found. The frontend bundle calls
baseURL: "https://api.brownbook.net/app"withapi/v1/...routes;businesses/resource/<id>returns the complete 92-field record as plain JSON with no cookies, no API key and no Cloudflare challenge. - The CAPTCHA route is deliberately skipped.
POST /app/api/v1/businesses/searchreturns HTTP 422Please complete the CAPTCHA verification to continue. This Actor never calls it. - Sitemap tree → the enumeration key.
robots.txtpublishesSitemap: https://api.brownbook.net/sitemap_indexes.xml, expanding into 31 index files → ~46,531 leaf sitemaps → ~46.5M<loc>https://www.brownbook.net/business/<id>/<slug>/</loc>URLs. Every record is keyed by its numeric ID, so the corpus is reachable without search: sitemap for IDs, JSON API for data.
Result: CheerioCrawler only — no Playwright, no browser, no session pool, no CAPTCHA solver, no Chrome process to pay for, yet the Actor still defaults to 2 GB of RAM (see below).
Scrape Brownbook Business Listings At Scale: Cost, RAM And Pricing
- 1 request per business for the full record — the API response is parsed straight from the crawl response, so it is not fetched twice. +1 request when
includeMediais on. - Reviews are free when embedded in the detail record; only businesses that may have more (5+ embedded, or none embedded but a rating) hit
/business/<id>/comments, capped at 5 pages of 5. Typical run: 2–3 requests per business, worst case 7. - 2,048 MB RAM by default (range 256–4,096). Pure HTTP makes memory cheap in compute units, but on Apify the CPU share grows with memory and too little of it throttles the autoscaled pool to ~3 in-flight requests. Same 1,000-business crawl: 59 s / $0.06 at the 2 GB default, 132 s / $0.08 at 1 GB, 240 s / $0.10 at 512 MB (100 businesses: ~5–9 s). 1 GB is the trap in the middle — half the RAM halves the CPU share, so the run more than doubles and costs more; a faster run is usually the cheaper run.
- Concurrency capped at 8 (run time scales almost linearly with it), retries capped at 3, 90 s per-request timeout. Raising the cap to 16 on the same crawl gave no gain (69 s vs 59 s): the pool settles at ~7–8 in flight, because per-request latency and CPU, not the cap, are the limit.
maxRequestsPerCrawl,maxItems, concurrency and timeouts are all hard-capped. - Free accounts are capped at 50 businesses; paying accounts are unlimited up to
maxItems(250,000).
Pay-per-event pricing
Reviews are billed separately from businesses: only items pushed to the default dataset are charged by the built-in result event, while reviews-dataset items are never billed automatically — which is why billableReviews() issues an explicit charge.
| Event | Billed when | Price |
|---|---|---|
result | a business row is written to the default dataset | $0.002 (FREE) → $0.0019 (GOLD+) |
Review | a review row is written to brownbookreviews | $0.001 → $0.0009 |
Actor Start | the run starts | $0.00005 |
Setup — Apify Console → this Actor → Monetization → Pay per event: add a custom event named Review (it must match REVIEW_EVENT in src/routes.ts) with the per-row price; optionally enable the synthetic apify-default-dataset-item event to bill business rows too (the platform charges dataset writes, no code needed); set minimalMaxTotalChargeUsd so a run cannot start without covering one result.
billableReviews() in src/main.ts then behaves like this:
- Not on pay-per-event, or
Reviewnot registered → reviews pushed free and a one-off[charge]warning says the setup is missing. - On pay-per-event →
Actor.charge({ eventName: 'review', count })runs before each review batch and onlychargedCountrows are pushed. - Budget exhausted (
eventChargeLimitReached) → remaining reviews are dropped and the platform stops the run. - Any charging error → the batch is pushed unpaid and logged; billing trouble never loses data.
maxItems and the review charge budget are independent. maxReviewsPerBusiness is the cheapest lever on the review bill: a cap of 5 skips most comments calls and cuts Review charges directly.
Integrations & Automation
- Apify API — every input field is a JSON property, so any run is one
POSTof the input object to the Actor's run endpoint (the Console's API tab pre-fills the exact URL and token); results come back from the dataset endpoint as JSON, CSV, Excel, XML, HTML or RSS. - Webhooks — fire on run success or dataset item creation and push rows into your CRM, warehouse or lead queue; the reviews dataset can carry its own webhook.
- Zapier and Make — native Apify integrations, so a finished run can append rows to Google Sheets, Airtable, HubSpot or Slack without code.
- Recommended schedule: weekly new-listing monitoring. Brownbook is community-edited, so a recurring run beats one giant crawl — schedule weekly with
startUrlson the highest leaf sitemaps (most recently updated listings) and a modestmaxItems, then diffupdatedAt/lastmod. Recurring schedules also improve Store recommendation signals.
Local Development
npm ci · npm run build (tsc) · npm run lint (eslint, zero warnings policy) · npm test (vitest: sitemap parsing + row building) · npm run start:dev. Local runs read input from storage/key_value_stores/default/INPUT.json, e.g. { "businessIds": "53562541,53562540", "maxItems": 10 }. Set APIFY_USER_IS_PAYING=1 to lift the 50-record free-account cap while testing; results land in storage/datasets/default and storage/datasets/brownbookreviews.
Related Actors
- brownbook-business-scraper — worldwide business details from
startUrls - brownbook-business-scraper — Brownbook search by keyword, location and country
- brownbook-email-scraper — public Brownbook emails by keyword and location
- yellowpages-scraper — Yellow Pages listings with phones, addresses, ratings, reviews
- yelp-business-scraper — Yelp listings by keyword, location or URL, no API key or browser
FAQ
What is the best way to access Brownbook business listings at scale?
Enumerate IDs from the public sitemap tree, then read each record from the JSON API. The index expands into 31 files and ~46,531 leaf sitemaps of 1,000 URLs, every <loc> carrying the numeric ID; GET .../businesses/resource/<id> returns the 92-field record as plain JSON with no cookies, API key or challenge. The search route (POST .../businesses/search) returns HTTP 422 CAPTCHA verification and is never called.
Is there an official Brownbook API?
Yes for records, no for bulk export: api.brownbook.net record, media, comments, countries, categories and autocomplete endpoints answer as plain JSON without authentication (docs.brownbook.net documents the API), but the search route is CAPTCHA-gated (HTTP 422). Bulk access means the published sitemap tree plus the per-record API — this Actor's entire path.
What are the alternatives to Brownbook for global business data?
Store options: brownbook-business-scraper, brownbook-business-scraper and brownbook-email-scraper, plus yellowpages-scraper and yelp-business-scraper. Commercial benchmarks are ZoomInfo, D&B, Infobel, Kompass, Yellow Pages and Yelp; this Actor is the pay-per-event route to Brownbook's 44M+ listings — the one that skips the CAPTCHA-gated search UI by enumerating the sitemap tree.
Can I export NAP data from Brownbook for local SEO citation building?
Yes — a core job of this Actor. Business rows carry name, address, addressLine1/2/3, city, state, zipCode/postcode, country/countryCode, lat/lng, phone and website; the Contact leads view flattens phone, mobile, email, website and socials, while claimed, claimVerified and claimEndDate show which listings still need claiming.
Are there cheaper alternatives to ZoomInfo and D&B for global business contact data?
Directory-based sources are the usual answer, and this Actor bills per event instead of by subscription: result $0.002 (FREE) → $0.0019 (GOLD+) per business row, Review $0.001 → $0.0009, Actor Start $0.00005 per run. Free accounts are capped at 50 businesses; paying accounts go to maxItems (250,000).
Can I legally scrape Brownbook listings for a commercial project?
Only public surfaces: robots.txt allows / and the sitemap tree, and the disallowed /ajax/, /account/*, /businesses/ and /review/add/ are never touched — no login, no authentication bypass, no CAPTCHA solving. Compliance with Brownbook's terms and data-protection law (GDPR/CCPA, since rows include contact data) is your responsibility — see Legal.
SEO Keywords
brownbook scraper, brownbook API, brownbook.net data, brownbook alternative, brownbook business listings, global business database, B2B contact database, company email phone database, citation building data, NAP data for local SEO, business directory data export, business data aggregator, sales intelligence data, B2B lead list, NAICS business data, Yellow Pages alternative, Yelp alternative for B2B, ZoomInfo alternative, D&B alternative, Infobel alternative, Kompass alternative
For AI Agents & LLM Apps
Machine-oriented reference for calling this Actor.
Purpose — enumerate brownbook.net business IDs from the public sitemap tree and return 92-field business records plus a separate reviews dataset.
Minimal working input (sitemap mode, trimmed to the free-account ceiling): { "sitemapIndex": "1", "sitemapLeafCount": "1", "maxItems": 50 }
Variant — enrichment mode (no crawling, one record per known ID): { "businessIds": "53562541,53562540", "maxItems": 10 }
Output field list — default dataset, grouped: identity/claim (id, legacyBusinessId, name, shortName, slug, url, claimed, claimVerified, claimEndDate, duplicateOf, closed); location (country, countryCode, state, city, area, address, addressLine1/2/3, zipCode, postcode, serviceArea, lat, lng); contact (phone, mobile, voip, fax, email, emails, website, websites, additionalPhones, additionalWebsites, additionalEmails); socials (socials, socialsPresent, facebook, twitter, instagram, linkedin, tiktok, youtube, skype, blog); classification (categories, category, naicsCode, naicsTitle, naicsBreadcrumb, naicsConfidence, tags, services, products, paymentOptions, yearEstablished); content/media (description, businessHours, hoursDisplay, logoUrl, imageCount, images, videoCount, videos, rating, reviewCount); meta (createdAt, updatedAt, indexedAt, lastmod, scrapedAt, source); meta rows (type, totalFound, indexCount, totalLeafSitemaps, estimatedBusinessUrls, data, mode, isPaying). Reviews dataset: type, reviewId, businessId, businessName, businessUrl, businessCountryCode, rating, comment, status, authorId, author, authorCountry, authorAvatar, mediaUrl, reply, createdAt, updatedAt, source, scrapedAt.
Behaviors an agent should know
- Mode priority —
businessIds,startUrlsorcountrySample: trueeach trigger their own mode; otherwise sitemap discovery runs fromsitemapIndex/sitemapLeafCount; with nothing set the run emits coverage/taxonomy rows only.detail: falsereturns sitemap IDs only, with no contact fields. - Bill-relevant defaults —
includeMedia: trueadds 1 request per business,includeReviews: truewrites review rows theReviewevent bills,maxReviewsPerBusiness: 0keeps every review (max 25 per business),maxItemsdefaults to 5000; free accounts stay hard-capped at 50 businesses and review rows never consume that budget. sitemapIndexaccepts a comma-separated list over the API ("2,3,4");sitemapLeavesandmaxLeafSitemapsare accepted as legacy aliases.- Keep the 2 GB default memory — CPU share scales with memory (1 GB measured 132 s / $0.08, 512 MB 240 s / $0.10, versus 59 s / $0.06 at 2 GB on the same 1,000 businesses). Concurrency is fixed at 8 (16 measured no gain), 3 retries, 90 s timeout.
reviewId, neverid— the platform rejectsidin a dataset schema withNOT SUPPORTED: keyword "id", use "$id".- Two datasets — business rows in
default, reviews in the aliasbrownbookreviews; read them separately.
Billing model — pay per event: result ($0.002 → $0.0019 per business row), Review ($0.001 → $0.0009 per review row), Actor Start ($0.00005 per run).
Legal & Compliance Disclaimer
This Actor is an independent third-party tool. It is not affiliated with, endorsed by, sponsored by or connected with brownbook.net or its operator.
It accesses only what the site publishes for all user-agents: the public sitemap tree (robots.txt allows / and the sitemap; it disallows /ajax/, /account/*, /businesses/ and /review/add/, none of which this Actor touches) and the public JSON record endpoints, which answer without cookies, credentials or an API key. No login, no authentication bypass, no CAPTCHA solving — the CAPTCHA-gated search endpoint (POST .../businesses/search, HTTP 422) is deliberately never called, and no browser is driven.
Output includes published business contact data — names, addresses, phone numbers, emails, websites and social profiles — plus third-party submitted review content. You are responsible for your own compliance with brownbook.net's terms of service and with applicable data-protection law (GDPR/CCPA where your use covers EU or California personal data), and this contact data must not be used for unsolicited commercial outreach in violation of applicable law. This Actor is a data-collection tool; it provides no legal advice and claims no particular use is permitted.