BBB Scraper
Pricing
from $4.00 / 1,000 results
BBB Scraper
Better Business Bureau (BBB) scraper & API: export US & Canada company profiles, BBB ratings & accreditation status, customer reviews & complaints, phone, address, website, category and years in business. B2B lead generation, due diligence and business reputation data — fast, no login.
Pricing
from $4.00 / 1,000 results
Rating
0.0
(0)
Developer
Haketa
Maintained by CommunityActor stats
0
Bookmarked
149
Total users
15
Monthly active users
a day ago
Last modified
Categories
Share
BBB Scraper — Better Business Bureau Business Profiles, Ratings, Complaints & Accreditation Data (US + Canada)
The most complete Better Business Bureau (BBB.org) scraper on Apify. This BBB scraper pulls full business profiles from BBB.org — letter-grade ratings, accreditation status, complaint counts, customer-review scores, owner/principal, phone, website, categories and firmographics — across the entire United States and Canada. Search by keyword, city, state, ZIP, or a ready-made BBB search URL and get clean, structured BBB data with no login and no coding.
Export to JSON, CSV, Excel, or API.
Built for B2B lead-generation teams, KYB / business-credit & risk analysts, reputation-monitoring and brand-protection teams, M&A due-diligence and services roll-up operators, contractor / vendor vetting procurement, and investigative journalists who need BBB trust signals at scale.
🔎 Why scrape BBB?
The Better Business Bureau is the largest non-profit business directory in North America, listing more than 5 million companies across the United States and Canada. A BBB profile is a de-facto trust signal for local and consumer-facing businesses — roofing contractors, plumbers, HVAC companies, home builders, movers, auto dealers and thousands of other categories maintain public BBB pages with a letter-grade rating, accreditation status, complaint history and customer reviews.
That makes BBB data uniquely valuable: it combines firmographics (name, address, phone, categories, years in business, owner) with a reputation layer (rating, accreditation, complaints, reviews) that almost no other free source exposes in one place. The problem is getting it out — BBB.org sits behind Cloudflare's JavaScript challenge, renders as a React/Next.js app, paginates its results and mixes organic listings with paid ads, so a naive requests/axios script just returns a "Just a moment…" page. This BBB.org scraper solves all of that: give it a keyword and location (or a BBB search URL) and it returns a clean, deduplicated, normalized dataset of every business BBB shows for that query.
Common reasons people scrape BBB:
- Build B2B lead lists of local-service businesses filtered by BBB rating and accreditation
- Enrich a CRM with BBB rating, accreditation, complaint counts and owner name for KYB / due diligence
- Monitor your own or competitor reputation (rating drift, new complaints) over time
- Screen M&A roll-up targets by rating and complaint exposure before spending analyst time
- Vet contractors / vendors (require rating ≥ B+ and accredited) for procurement panels
- Investigate clusters of high-complaint businesses in a category and metro for journalism / consumer protection
- Size a local-services TAM by counting accredited, highly-rated businesses per metro and category
✨ What this BBB scraper does
This is a production-grade Apify Actor that scrapes BBB business profiles end to end:
- ✅ Two search modes — search by
keyword+location+country, or paste ready-made BBB search URLs insearchUrlsto run exact queries (multiple at once). - ✅ Automatic pagination — walks BBB's result pages (≈15 businesses per page) up to
maxPages, deduplicates across pages and across queries on the canonical profile URL, and returns hundreds of unique records per run. - ✅ Cloudflare bypass — a real Chromium browser (headed, under Apify's virtual display) transparently clears BBB's JS challenge where plain HTTP clients get a 403.
- ✅ Structured-state extraction — the actor reads BBB's embedded
window.__PRELOADED_STATE__React state, the authoritative source for every field, so results survive BBB's periodic HTML redesigns. JSON-LD, CSS and free-text parsing remain as fallbacks. - ✅ Rich search-card fields — even without detail enrichment you get business name, BBB profile URL, BBB ID, BBB letter-grade rating, phone, categories, city, state and ZIP for every card.
- ✅ Full profile enrichment — turn on
scrapeDetailsto add accreditation status + date, complaint counts (total / last 3 years / last 12 months), customer-review count + average star rating, owner/principal, business type (LLC / Corp / …), years in business, business start date, website, description, social-media links and license details. - ✅ Ad & sub-page filtering — paid DoubleClick/Google-Ads listings are dropped;
/details,/accreditation,/customer-reviews,/complaintssub-pages are collapsed to one canonical profile. - ✅ Business-only socials — Facebook / LinkedIn / X / Instagram links are filtered against BBB's own accounts and share-intent URLs, so you only get the business's channels.
- ✅ USA + Canada — toggle
countrybetweenUSAandCAN; locations accept city + state/province, state/province alone, or ZIP / postal code. - ✅ Export anywhere — JSON, CSV, Excel, HTML, XML, RSS or JSON Lines, plus the Apify API, webhooks and native Make / Zapier / n8n / Google Sheets integrations.
🎯 Use cases
- B2B sales & lead-gen — pull every roofing contractor, HVAC company or plumber in a metro, keep only
A-+ accredited businesses, and push into your outbound sequence. - KYB & business-credit risk — enrich onboarding with BBB rating, accreditation and
complaintsLast12Mo; flag rating downgrades on a schedule. - Reputation monitoring — track every franchise location for rating drops, new complaints or accreditation lapses; diff weekly snapshots.
- M&A due diligence — screen services roll-up targets by rating and complaint exposure; identify the owner/principal for direct outreach.
- Contractor & vendor vetting — pre-approve vendors that are accredited and
B++ and re-validate the panel automatically. - Compliance & anti-fraud — queue or block merchants with
Fratings or a spike in recent complaints during KYB onboarding. - Journalism & consumer protection — surface clusters of high-complaint movers, debt-relief mills or solar door-knockers in a category + metro.
- Market research — count accredited, highly-rated businesses per metro and category to size a local-services TAM.
📥 Input
Configure a run from the Apify Console form or via the API. Every field is optional — run with no input at all and the actor returns a diverse ~100-business sample across popular categories and major US metros.
| Parameter | Type | Default | Description |
|---|---|---|---|
keyword | string | roofing contractor | Business type, profession or company name — e.g. plumber, HVAC, home builder, auto repair, moving company, dentist. Leave empty for a mixed sample. |
location | string | Dallas, TX | City + state, state alone, or ZIP / postal code — e.g. Houston, TX, California, 90210, Toronto, ON. |
country | string enum | USA | USA (United States) or CAN (Canada). Drives BBB's find_country parameter. |
sort | string enum | Relevance | Result order: Relevance, Rating, Distance or Name. |
accreditedOnly | boolean | false | When true, drop any listing explicitly marked Not BBB Accredited. |
scrapeDetails | boolean | false | When true, open each business profile and fill complaints, reviews, owner, accreditation date, website, description, social media and license details. Richer but slower. |
maxResults | integer | 0 (prefill 100) | Hard cap on total businesses saved. 0 = unlimited. |
maxPages | integer | 10 | Max result pages per search (≈15 businesses each). |
searchUrls | array | [] | Advanced: ready-made BBB search URLs to run exactly as-is. When set, keyword / location / country / sort are ignored. |
proxyConfiguration | object | { useApifyProxy: false } | Optional proxy. Start without one; enable Apify Proxy (residential) only if BBB throttles large runs. |
requestDelay | integer (ms) | 500 | Pause between requests. Higher = gentler and more reliable (capped at ~2 s). |
maxConcurrency | integer | 2 | Parallel detail-profile workers. Capped at 2 for stable operation inside the default 1 GB memory. |
Example input — keyword + location, full enrichment
{"keyword": "roofing contractor","location": "Dallas, TX","country": "USA","sort": "Rating","accreditedOnly": false,"scrapeDetails": true,"maxResults": 200,"maxPages": 15,"requestDelay": 500,"maxConcurrency": 2,"proxyConfiguration": { "useApifyProxy": false }}
Multi-metro TAM: pass several BBB search URLs in searchUrls (one per keyword × city), set maxResults: 0 and maxPages: 15, and the actor walks and deduplicates them all into one dataset — e.g. .../search?find_text=roofing+contractor&find_loc=Houston%2C+TX&find_country=USA plus the Dallas and Austin equivalents.
📤 Output
Every record is a flat JSON object with a stable column set — fields not present on a given profile come back as null, so listing-only and detail-enriched runs share the same schema and load cleanly into a CRM, warehouse or spreadsheet without per-field branching.
Example — search-card record (scrapeDetails: false)
Fresh output from a live run (roofing contractor, Dallas TX):
{"businessName": "Home Integrity Solutions LLC","profileUrl": "https://www.bbb.org/us/tx/dallas/profile/roofing-contractors/home-integrity-solutions-llc-0875-91349575","bbbId": "91349575","bbbRating": "A","isAccredited": null,"accreditationSince": null,"address": null,"city": "Dallas","state": "TX","zipCode": "75205-5565","phone": "(214) 498-6458","email": null,"website": null,"categories": ["Roofing Contractors", "Home Renovation", "Roof Inspection", "Roof Replacement"],"serviceAreas": null,"yearsInBusiness": null,"businessStartDate": null,"businessType": null,"numberOfEmployees": null,"ownerName": null,"licenseNumbers": null,"complaintsTotal": null,"complaintsLast3Yrs": null,"complaintsLast12Mo": null,"complaintsResolved": null,"reviewCount": null,"averageReviewRating": null,"socialMedia": null,"governmentActions": null,"description": null,"searchKeyword": "roofing contractor","searchLocation": "Dallas, TX","scrapedAt": "2026-11-02T00:10:35.995Z"}
Example — fully enriched record (scrapeDetails: true)
{"businessName": "Ecotech Roofing and Construction","profileUrl": "https://www.bbb.org/us/tx/dallas/profile/roofing-contractors/ecotech-roofing-and-construction-0875-90228991","bbbId": "90228991","bbbRating": "A+","isAccredited": true,"accreditationSince": "8/10/2009","address": "3130 Harvard Ave Ste B","city": "Dallas","state": "TX","zipCode": "75219-5305","phone": "(972) 922-3606","email": null,"website": "https://ecotechroofing.example","categories": ["Roofing Contractors", "Gutters", "Commercial Roofing", "Replacement Windows", "Storm Damage Repair", "Residential Roofing"],"serviceAreas": null,"yearsInBusiness": 17,"businessStartDate": "2/23/2009","businessType": "Limited Liability Company (LLC)","numberOfEmployees": "25","ownerName": "Mr. Robert Burnley","licenseNumbers": null,"complaintsTotal": 0,"complaintsLast3Yrs": 0,"complaintsLast12Mo": 0,"complaintsResolved": null,"reviewCount": 19,"averageReviewRating": 4.95,"socialMedia": { "facebook": "https://www.facebook.com/ecotechroofing", "instagram": "https://www.instagram.com/ecotechroofing/" },"governmentActions": null,"description": "Full-service residential and commercial roofing contractor serving the Dallas–Fort Worth metroplex.","searchKeyword": "roofing contractor","searchLocation": "Dallas, TX","scrapedAt": "2026-11-02T00:10:35.996Z"}
Field reference
| Field | Type | Description |
|---|---|---|
businessName | string | Company / DBA name as shown by BBB |
profileUrl | string | Canonical BBB profile URL (sub-pages stripped) — natural key |
bbbId | string | BBB's stable numeric business identifier |
bbbRating | string | Letter grade: A+,A,A-,B+,B,B-,C+,C,C-,D+,D,D-,F or NR |
isAccredited | boolean | true if BBB-accredited, false if explicitly not, null if undetermined (resolves on detail pages) |
accreditationSince | string | Accreditation start date, M/D/YYYY (detail mode) |
address | string | Street address (present when BBB displays it) |
city | string | City |
state | string | Two-letter US state / Canadian province code |
zipCode | string | ZIP (5 or 9-digit) or Canadian postal code |
phone | string | Business phone number |
email | string | Contact email (present when BBB publishes it; often blank) |
website | string | Business website (BBB redirects/share links filtered; detail mode) |
categories | array | BBB business categories |
serviceAreas | array | Cities/regions served (present when listed) |
yearsInBusiness | integer | Years operating (detail mode) |
businessStartDate | string | Reported business start date, M/D/YYYY (detail mode) |
businessType | string | Legal structure, e.g. Limited Liability Company (LLC), Corporation (detail mode) |
numberOfEmployees | string | Employee count as reported (present when disclosed) |
ownerName | string | Owner / principal / management contact (detail mode) |
complaintsTotal | integer | All-time BBB complaints closed (detail mode) |
complaintsLast3Yrs | integer | Complaints closed in the last 3 years (detail mode) |
complaintsLast12Mo | integer | Complaints closed in the last 12 months (detail mode) |
reviewCount | integer | Customer-review count (detail mode) |
averageReviewRating | number | Average customer review 1.0–5.0 (present when reviews exist) |
socialMedia | object | { facebook, linkedin, twitter, instagram } — business's own accounts (detail mode) |
description | string | "About this business" narrative (present when provided) |
searchKeyword / searchLocation | string | The query that surfaced this business |
scrapedAt | string | ISO-8601 extraction timestamp |
licenseNumbers, complaintsResolved, governmentActions | — | Reserved keys, always present for a stable schema; licenseNumbers populates when BBB lists license details, the other two return null by default |
Honest field coverage (from a fresh verification run). In listing-only mode, identity fields (businessName, profileUrl, bbbId, city, state, zipCode) and categories come back at ~100%, bbbRating ~99.8% and phone ~98%; isAccredited and all detail-only fields stay null until you enable scrapeDetails. In detail mode, bbbRating, isAccredited, accreditationSince, categories, complaintsTotal/3Yrs/12Mo, reviewCount, ownerName, businessType, yearsInBusiness, businessStartDate, zipCode and phone populate at ~100%, while website, averageReviewRating, description, socialMedia, numberOfEmployees, email and licenseNumbers are present when BBB displays them (data-dependent, not every business discloses them).
🔁 Pagination & scale
BBB serves search results in pages of about 15 businesses via a page=N query parameter. The actor walks pages sequentially for each query until it reaches maxPages, runs out of results, or hits maxResults. BBB caps a single query at roughly 15 pages (~200–225 businesses) even when the total match count is far larger (a single roofing contractor / Dallas, TX query reports 7,320 total results), so to build large datasets you split the work across multiple searchUrls — different keyword × city pairs — and the actor merges and deduplicates them into one dataset on the canonical profile URL.
Results are deduplicated both within and across queries, so you never get the same business twice. A representative verification run collected 400 unique businesses across 5 metros with 0 duplicates. Control the volume with maxResults (set 0 for unlimited) and maxPages.
⚙️ How to use
- On the Apify Console — open the actor, set a
keyword+location(or pastesearchUrls), optionally togglescrapeDetails, and click Start. - Via API —
POST https://api.apify.com/v2/acts/haketa~bbb-scraper/runs?token=YOUR_TOKENwith your input JSON; poll the run and read the dataset. - On a schedule — use Apify's Scheduler (any cron) for a daily watchlist, weekly TAM rebuild, or monthly competitor diff.
- Choose an export — JSON, CSV, Excel, HTML, XML, RSS or JSON Lines from the dataset view or the
…/itemsendpoint. - Integrate — pipe results into Make, Zapier, n8n, Google Sheets, Slack, a webhook, or your warehouse (Postgres / Snowflake / BigQuery) using
bbbIdorprofileUrlas the upsert key.
API run (Python)
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("haketa/bbb-scraper").call(run_input={"keyword": "roofing contractor", "location": "Dallas, TX","sort": "Rating", "scrapeDetails": True, "maxResults": 200, "maxPages": 15,})for r in client.dataset(run["defaultDatasetId"]).iterate_items():print(r["bbbRating"], r["businessName"], r["city"], r["complaintsLast3Yrs"], r["profileUrl"])
Or via cURL: POST https://api.apify.com/v2/acts/haketa~bbb-scraper/runs?token=YOUR_APIFY_TOKEN with your input JSON.
💡 Tips
- Start listing-only. With
scrapeDetails: falseyou already get name, rating, phone, categories, city, state and ZIP at ~20× the throughput — enough for most lead-scoring. FlipscrapeDetails: trueonly for the high-value records you need to enrich. - Scale with
searchUrls, not justmaxPages. Because BBB caps one query near 15 pages, the way to pull thousands of businesses is many keyword × city URLs in a single run. - Filter to accredited prospects with
accreditedOnly: truefor higher reply rates, or sort by rating withsort: "Rating". - Only add a proxy if BBB throttles a large run — start with
useApifyProxy: false. If you do enable it, Apify residential proxies are the most reliable; the actor already blocks heavy image/media/font traffic to keep proxy cost down. - Use
bbbId(orprofileUrl) as your natural key for warehouse upserts and cross-run diffs (e.g. detecting rating downgrades). - Canada: set
country: "CAN"with a Canadian location such asVancouver, BCorToronto, ON.
❓ FAQ
Is scraping BBB legal? The actor collects only public data any visitor can see on BBB.org without logging in. Review BBB's Terms of Use before commercial redistribution and comply with downstream marketing law (CAN-SPAM, TCPA, CASL, GDPR/CCPA). A BBB listing is a trust signal, not consent to be marketed to.
How many results will I get, and how fast?
You control it with maxResults and maxPages. One query tops out near ~200–225 businesses (BBB's ~15-page cap), so combine searchUrls for larger sets. A verification run returned 400 unique businesses across 5 metros in a few minutes; listing-only pages take ~5–10 s each, detail profiles a few seconds each.
Do I need a BBB account or API key? No. BBB has no public API. This BBB API alternative scrapes the public website directly, no login required.
Do I need proxies? Not for small or moderate runs — start with no proxy. For very large or heavily-scheduled runs, enable Apify residential proxy only if you see throttling.
How does it get past Cloudflare? It launches a real Chromium browser in headed mode under Apify's virtual display, applies stealth tweaks, and waits for Cloudflare's JS challenge to clear before reading the page — so you get data instead of a "Just a moment…" page.
How fresh is the BBB data? Live at run time. There's no cache between you and BBB; every record reflects exactly what BBB.org served at scrape time.
Can I filter to accredited businesses, or sort by rating?
Yes — set accreditedOnly: true and/or sort: "Rating".
Does it include complaints and reviews? It returns complaint counts (total / last 3 years / last 12 months) and the customer-review count + average star rating. Full complaint narratives and individual review text live on separate paginated sub-pages and are out of scope.
Why are some fields empty?
The schema is stable; fields BBB doesn't display for a given business come back null. email, website, numberOfEmployees, description and licenseNumbers are data-dependent — they populate only when the business disclosed them to BBB.
Does it work for Canada?
Yes. Set country: "CAN" and a Canadian location; the actor follows BBB's find_country=CAN pattern.
What export formats are available? JSON, CSV, Excel, HTML, XML, RSS and JSON Lines, plus the Apify API and webhooks.
🔗 Related scrapers
BBB data is most powerful joined to other public-business datasets for lead-gen, KYB, contractor vetting, compliance and journalism:
- 🏢 Dun & Bradstreet Scraper — Companies, DUNS & Revenue — firmographics, DUNS numbers and revenue bands for entity enrichment
- 🇺🇸 SBA Small Business Search Scraper — US small businesses registered for federal contracting, with NAICS and contacts
- 🚀 YCombinator Companies Scraper — the full Y Combinator startup directory for tech lead lists
- 🧰 BuiltIn.com Tech Companies & Tech Stack Scraper — tech employers, hiring data and technology stacks
- 🇪🇺 Impressum & EU Legal Notice Extractor — company name, VAT ID and legal contact from EU websites
- 🇺🇸 Arizona ROC Contractor License Scraper — Arizona Registrar of Contractors
- 🇺🇸 Washington L&I Contractor License Scraper — Washington Labor & Industries registry
Pattern: pull a BBB dataset for a category + metro, enrich with the matching state-licensing actor on businessName / ownerName, then add D&B or SBA firmographics — a three-source view of every business in your TAM in a few runs.
📅 Changelog & maintenance
Last updated: 2026-11-01 — v1.1.0. Major extraction fix for BBB's React/Next.js redesign: the scraper now reads window.__PRELOADED_STATE__ as the authoritative source, restoring bbbRating on search cards (0% → ~100%) and full detail-page enrichment (accreditation, complaints, reviews, categories, owner, firmographics). Verified on a fresh run of 400 unique businesses across 5 US metros with 0 duplicates and 100% identity-field coverage. See CHANGELOG.md for the full history.
If this BBB scraper saves you time, a ⭐ rating on the Apify Store helps other B2B, compliance, journalism and reputation teams find it. Thank you!