BBB Scraper
Pricing
from $4.00 / 1,000 results
BBB Scraper
Scrape business profiles from Better Business Bureau (BBB.org). Extract BBB ratings, accreditation status, complaints, reviews, owner info, license numbers and contact details. Search by keyword, location, category and country (USA/Canada).
Pricing
from $4.00 / 1,000 results
Rating
0.0
(0)
Developer
Haketa
Maintained by CommunityActor stats
0
Bookmarked
11
Total users
6
Monthly active users
3 days ago
Last modified
Categories
Share
BBB Scraper — Better Business Bureau Business Profiles, Ratings, Complaints & Accreditation Data Extractor (US + Canada)
The most complete Better Business Bureau (BBB.org) data extraction tool on Apify. Pull full business profiles from BBB — letter grade ratings, accreditation status, complaint counts, customer review scores, owner details, license numbers and contact info — across the entire United States and Canada. Search by keyword, city, state, ZIP, or pre-built BBB search URL, and ship structured JSON ready for B2B lead generation, business-credit risk analysis, reputation monitoring, M&A due diligence, contractor vetting, and journalism workflows.
What This Actor Does
The BBB Scraper is a production-grade Apify Actor that extracts complete business profiles from the Better Business Bureau (BBB.org) — the largest non-profit business directory in North America, covering more than 5 million companies across the United States and Canada. BBB profiles are widely treated as a de-facto trust signal for local services: roofing contractors, plumbers, HVAC companies, home builders, auto dealers, movers, financial advisors, debt collectors, e-commerce brands, and thousands of other categories all maintain public BBB pages.
This actor opens a real Chromium browser via Playwright (in headed mode under Apify's virtual display), navigates BBB search results and business profile pages, transparently solves Cloudflare's JavaScript challenge, and parses each profile into a normalized JSON record. You drive it with a keyword + location (e.g. "roofing contractor" in "Dallas, TX") or by pasting direct BBB search URLs, and you get back a structured dataset of every business that BBB shows for that query.
Each record can include:
- Identity — business name, BBB business ID, full BBB profile URL
- Trust signals — BBB letter-grade rating (A+ through F), accreditation status, accreditation start date
- Contact — street address, city, state/province, ZIP/postal code, phone, email, website
- Categorization — business categories, service areas, line of business
- Firmographics — years in business, business start date, business type (LLC / Corporation / Sole Proprietorship), employee count band, owner / principal name
- Compliance — license numbers reported to BBB, government action narratives
- Reputation — total complaints closed, complaints in the last 3 years, complaints in the last 12 months, complaints resolved, customer review count, average customer review rating
- Channels — social media URLs (Facebook, LinkedIn, X/Twitter, Instagram) belonging to the business itself, not BBB's own accounts
- Provenance — source search keyword, source search location, ISO-8601
scrapedAttimestamp
The result is the fastest way to populate or refresh a BBB-anchored business dataset for B2B lead generation, reputation monitoring, vendor onboarding, contractor vetting, and investigative reporting.
Why scrape BBB yourself when this exists?
BBB looks like a simple directory until you try to scrape it at scale. Almost every team that tries to roll their own pipeline hits the same wall:
- BBB.org sits behind Cloudflare's JS challenge — naive HTTP clients (
requests,axios,got, evengot-scraping) get a 403 and an HTML "Just a moment…" page instead of data - Cloudflare also fingerprints headless Chromium — running Playwright in plain
headless: truemode is detected within seconds and challenged on every request - The search page is React-rendered, so the business cards do not exist in the initial HTML and require a real DOM to materialize
- Pagination is URL-driven (
?page=2,?page=3…) but BBB silently caps deep pagination and serves partial pages near the end of a result set - Result cards mix organic businesses with paid ads that link out through DoubleClick / Google Ads — those entries have to be filtered out or they pollute your dataset
- Profile URLs include duplicate sub-pages (
/details,/accreditation,/customer-reviews,/complaints,/addressId) that all need to be deduplicated to one canonical profile per business - Profile pages mix JSON-LD structured data, free-text "About this business" prose, and CSS-class-driven panels — extracting accreditation, complaints, owner, and business start date reliably requires four different parsing strategies
- Email addresses on profiles are protected by Cloudflare's email obfuscation (
data-cfemail="...") — they have to be decoded with the XOR-key trick before they are readable - BBB rate-limits aggressively; running anything beyond single-digit concurrency triggers temporary IP blocks
- Categories, service areas, and license numbers live in CSS class names that drift every few months — the parser needs fuzzy class matching that survives BBB's redesigns
This actor solves every one of those problems out of the box. You provide a keyword and location; it returns clean, deduplicated, normalized JSON with all of the BBB trust signals you actually need.
Quick Start
One-Click Run
- Open the actor on the Apify Store: apify.com/haketa/bbb-scraper
- Click "Try for free" and accept the defaults (
roofing contractorinDallas, TX, 5 results, no detail pages) - Hit Start — within a minute or two you will have your first dataset of business cards
- Toggle Scrape Detail Pages to
trueand bump Max Results to100for a full enrichment run
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","country": "USA","accreditedOnly": True,"sort": "Rating","scrapeDetails": True,"maxResults": 200,"maxPages": 10,"requestDelay": 2500,"proxyConfiguration": {"useApifyProxy": True,"apifyProxyGroups": ["RESIDENTIAL"]}})for record in client.dataset(run["defaultDatasetId"]).iterate_items():print(record["bbbRating"],record["businessName"],record["city"],record["complaintsLast3Yrs"],record["profileUrl"],)
API Run (Node.js / TypeScript)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('haketa/bbb-scraper').call({keyword: 'HVAC',location: 'Phoenix, AZ',country: 'USA',accreditedOnly: false,sort: 'Relevance',scrapeDetails: true,maxResults: 100,maxPages: 5,proxyConfiguration: {useApifyProxy: true,apifyProxyGroups: ['RESIDENTIAL'],},});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(`Pulled ${items.length} Phoenix HVAC companies from BBB`);const aPlusAccredited = items.filter((b) => b.bbbRating === 'A+' && b.isAccredited === true,);console.log(`${aPlusAccredited.length} are A+ rated AND BBB Accredited`);
API Run (cURL)
curl -X POST "https://api.apify.com/v2/acts/haketa~bbb-scraper/runs?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"keyword": "plumber","location": "Toronto, ON","country": "CAN","scrapeDetails": false,"maxResults": 50}'
Direct-URL mode (skip keyword/location, use BBB URLs you already have)
run = client.actor("haketa/bbb-scraper").call(run_input={"searchUrls": ["https://www.bbb.org/search?find_text=electrician&find_loc=Brooklyn%2C+NY&find_country=USA","https://www.bbb.org/search?find_text=auto+repair&find_loc=Los+Angeles%2C+CA&find_country=USA"],"scrapeDetails": True,"maxResults": 0, # unlimited"maxPages": 15})
How It Works
The actor talks to a single host — www.bbb.org — and walks two layers of pages:
- Search results pages at
https://www.bbb.org/search?find_text={keyword}&find_loc={location}&find_country={USA|CAN}&page={N}&sort={Relevance|Rating|Distance|Name} - Business profile pages at
https://www.bbb.org/{us|ca}/{state}/{city}/profile/{category-slug}/{business-slug}-{bbbId}
Source endpoints
| Layer | URL pattern | Purpose | Engine |
|---|---|---|---|
| Search | bbb.org/search?find_text=...&find_loc=...&find_country=...&page=N | List business cards 20 per page | Playwright + Cheerio |
| Profile | bbb.org/{country}/{state}/{city}/profile/{category}/{slug}-{bbbId} | Full firmographics, complaints, reviews | Playwright + Cheerio |
| JSON-LD | Embedded <script type="application/ld+json"> on profile pages | Structured business name, address, phone, ratings | Cheerio JSON parse |
Engineering details
- Headed Playwright Chromium — runs with
headless: falseunder Apify'sxvfbvirtual display. Headless Chromium is detected and challenged by Cloudflare almost immediately; headed mode under xvfb passes the same fingerprint checks a real browser passes. - Stealth init script —
navigator.webdriveris set toundefinedandwindow.chrome.runtimeis stubbed before any page navigates, killing the two most common bot-detection flags. - Cloudflare challenge loop — every navigation enters a 15-step wait loop that watches
document.titleand the first 200 chars ofbody.innerTextfor the stringsJust a moment,Checking your browser, andVerify you are human. The loop exits as soon as real<a href*="/profile/">links appear or the body length crosses 500 characters. - Custom UA + viewport — Chrome 124 on Windows 10 at 1920x1080,
en-USlocale, JavaScript enabled. - Cheerio parsing — once the HTML is in hand, parsing is done with Cheerio in-process (zero browser overhead per field extraction).
- Ad filtering — search-card links that go through
doubleclick.net,adclick, orgoogleadsare dropped before they reach the dataset. - Sub-page deduplication — links ending in
/details,/accreditation,/customer-reviews,/complaints, or/addressIdare stripped down to the canonical profile URL and deduplicated via aSet. - BBB ID extraction — the trailing
-XXXXXXXXnumeric segment of the profile slug becomes the stablebbbId. - Multi-strategy field extraction — accreditation, complaints, owner name, business type, and employee count are extracted from (a) JSON-LD
Organization/LocalBusinessblocks, (b) CSS-class-keyed panels, and (c) free-text regex over the full page body. First non-null wins. - Cloudflare email decoder —
data-cfemailattributes are decoded with the XOR-key trick (first byte = key, remaining bytes XORed) so obfuscated emails become readable. - Social media hygiene — Facebook / LinkedIn / X / Instagram URLs are filtered against a blocklist of BBB's own accounts (
betterbusinessbureau,bbb_us, share-intent URLs) so you only get the business's socials. - Random-jitter delay — each subsequent request waits
requestDelay + random(0–1000ms)to avoid forming a detectable cadence. - Single-concurrency default —
maxConcurrency = 1and capped at3. BBB rate-limits aggressively; speed comes fromrequestDelaytuning, not parallelism. - Graceful partial output — fatal errors flush whatever was already collected and call
Actor.exitwith a non-zero exit code so the run is visibly failed without losing progress.
Input Parameters
{"searchUrls": [],"keyword": "roofing contractor","location": "Dallas, TX","country": "USA","accreditedOnly": false,"sort": "Relevance","scrapeDetails": false,"maxResults": 100,"maxPages": 10,"requestDelay": 1500,"maxConcurrency": 1,"proxyConfiguration": { "useApifyProxy": false }}
Parameter reference
| Parameter | Type | Default | Description |
|---|---|---|---|
searchUrls | array<string> | [] | Pre-built BBB search URLs. When provided, keyword / location / country / sort are ignored and the actor walks each URL through maxPages. Use this when you already have a curated BBB URL list. |
keyword | string | roofing contractor | Business type, profession, or company-name query. Examples: plumber, HVAC, home builder, electrician, moving company, auto repair, dentist, mortgage broker, tree service. |
location | string | Dallas, TX | City + state, state only, or ZIP / postal code. Examples: Houston, TX, California, 90210, Toronto, ON, Vancouver, BC. |
country | string enum | USA | USA for the United States, CAN for Canada. Drives the find_country query param. |
accreditedOnly | boolean | false | When true, filters out any listing that is not BBB Accredited. |
sort | string enum | Relevance | Sort order for search results: Relevance, Rating, Distance, or Name. |
scrapeDetails | boolean | false | When true, the actor opens every business profile page and fills complaints, reviews, owner, license numbers, social media, business start date, employee count, and full address. Adds ~3–6 seconds per business. |
maxResults | integer | 100 | Hard cap on total businesses saved. 0 means unlimited. |
maxPages | integer | 10 | Maximum search pages walked per task. Each page = ~20 results. |
requestDelay | integer (ms) | 1500 | Base delay between requests. Random jitter of 0–1000 ms is added on top. Keep ≥ 1000 ms to avoid blocks. |
maxConcurrency | integer | 1 | Parallel browser pages. Max 3. BBB rate-limits aggressively — leave at 1 unless you have residential proxies and are willing to monitor for blocks. |
proxyConfiguration | object | { useApifyProxy: false } | Standard Apify proxy block. Residential proxies strongly recommended for runs above ~50 businesses or whenever you see Cloudflare challenge loops. |
Output Schema
Every record is a flat JSON object so it can be loaded directly into a CRM, warehouse, spreadsheet, or BI tool without per-field branching. Fields that were not present on a given profile come back as null (so the schema is stable across listing-only and detail-enriched runs).
Identity fields
| Field | Type | Description |
|---|---|---|
businessName | string | Company / DBA name as displayed by BBB |
profileUrl | string | Canonical BBB profile URL (sub-pages stripped) |
bbbId | string | BBB's stable business identifier (trailing digits in the profile slug) |
Trust signals
| Field | Type | Description |
|---|---|---|
bbbRating | string | Letter grade — one of A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F, or NR (no rating) |
isAccredited | boolean | true if the page shows "BBB Accredited Business since…", false if explicitly "Not BBB Accredited", null if undetermined |
accreditationSince | string | Accreditation start date as printed on the profile (e.g. 5/12/2017, March 2009, 2003) |
Contact fields
| Field | Type | Description |
|---|---|---|
address | string | Street address as reported to BBB |
city | string | City |
state | string | Two-letter US state or Canadian province abbreviation |
zipCode | string | ZIP code (5 or 9 digits, US) or postal code (Canada) |
phone | string | Business phone number — pulled from tel: link, JSON-LD, or visible text |
email | string | Business contact email — Cloudflare-obfuscated emails are decoded |
website | string | Business website URL (BBB redirect URLs and share links filtered out) |
Categorization
| Field | Type | Description |
|---|---|---|
categories | array<string> | BBB business categories (e.g. ["Roofing Contractors", "Construction"]) |
serviceAreas | array<string> | Cities / regions the business reports serving |
Firmographics
| Field | Type | Description |
|---|---|---|
yearsInBusiness | integer | Computed from businessStartDate |
businessStartDate | string | Date the business reports having started (e.g. 1/1/2008) |
businessType | string | Legal structure — LLC, Corporation, Sole Proprietorship, Partnership, Inc, LP, LLP |
numberOfEmployees | string | Employee count band as printed on BBB (e.g. 25 to 50, 5) |
ownerName | string | Owner / principal / management contact name |
licenseNumbers | array<string> | License numbers the business has registered with BBB |
Reputation
| Field | Type | Description |
|---|---|---|
complaintsTotal | integer | All-time BBB complaints closed for the business |
complaintsLast3Yrs | integer | BBB complaints closed in the last 3 years |
complaintsLast12Mo | integer | BBB complaints closed in the last 12 months |
complaintsResolved | integer | BBB complaints resolved to the customer's satisfaction |
reviewCount | integer | Number of customer reviews submitted on BBB |
averageReviewRating | number | Average customer review score (1.0 – 5.0) |
Channels & narratives
| Field | Type | Description |
|---|---|---|
socialMedia | object | { facebook, linkedin, twitter, instagram } — only the business's own accounts |
governmentActions | string | Free-text summary of government / regulatory actions noted on the profile |
description | string | "About this business" narrative |
Provenance
| Field | Type | Description |
|---|---|---|
searchKeyword | string | The keyword used to find this business |
searchLocation | string | The location used to find this business |
scrapedAt | string | ISO-8601 timestamp of extraction |
Example: search-only record (scrapeDetails: false)
{"businessName": "Skyline Roofing & Solar","profileUrl": "https://www.bbb.org/us/tx/dallas/profile/roofing-contractors/skyline-roofing-solar-0875-90719612","bbbId": "90719612","bbbRating": "A+","isAccredited": true,"accreditationSince": null,"address": "5050 Quorum Dr Ste 700","city": "Dallas","state": "TX","zipCode": "75254","phone": "+1 214 555 0142","email": null,"website": null,"categories": ["Roofing Contractors", "Solar Energy Contractors"],"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-05-16T14:22:11.401Z"}
Example: fully enriched record (scrapeDetails: true)
{"businessName": "Northstar HVAC Services LLC","profileUrl": "https://www.bbb.org/us/az/phoenix/profile/heating-and-air-conditioning/northstar-hvac-services-1126-99999001","bbbId": "99999001","bbbRating": "A","isAccredited": true,"accreditationSince": "3/14/2014","address": "2400 W Camelback Rd Ste 210","city": "Phoenix","state": "AZ","zipCode": "85015","phone": "+1 602 555 0188","email": "service@northstar-hvac.example","website": "https://northstar-hvac.example","categories": ["Heating and Air Conditioning", "Air Duct Cleaning", "Furnace Repair"],"serviceAreas": ["Phoenix", "Scottsdale", "Tempe", "Mesa", "Glendale", "Chandler"],"yearsInBusiness": 17,"businessStartDate": "1/1/2008","businessType": "LLC","numberOfEmployees": "25 to 50","ownerName": "Maria S. Alvarez","licenseNumbers": ["ROC 99999", "ROC 99998"],"complaintsTotal": 12,"complaintsLast3Yrs": 7,"complaintsLast12Mo": 2,"complaintsResolved": 6,"reviewCount": 184,"averageReviewRating": 4.6,"socialMedia": {"facebook": "https://www.facebook.com/northstarhvacaz","linkedin": "https://www.linkedin.com/company/northstar-hvac","instagram": "https://www.instagram.com/northstar.hvac/"},"governmentActions": null,"description": "Full-service residential and commercial HVAC contractor serving the Phoenix metro since 2008. NATE-certified technicians, 24/7 emergency service.","searchKeyword": "HVAC","searchLocation": "Phoenix, AZ","scrapedAt": "2026-05-16T14:25:48.117Z"}
BBB Rating Reference
BBB issues a single letter-grade rating per business on a 13-point scale plus a "not rated" bucket. The rating is computed from complaint history, transparency of the business, time in operation, government action, advertising practices, and licensing.
Investment-grade ratings (low risk, default vendor whitelist)
| Rating | Meaning |
|---|---|
A+ | Top score — clean complaint history + transparent + tenured |
A | Excellent — minor blemishes but resolved |
A- | Very good — small number of unresolved items |
Sub-investment ratings (still operating, vet manually)
| Rating | Meaning |
|---|---|
B+ / B / B- | Above average — review complaint themes before engagement |
C+ / C / C- | Average — pattern of complaints or limited transparency |
D+ / D / D- | Poor — recurring unresolved complaints, government action, or short history |
Distressed (high risk, recommend exclude)
| Rating | Meaning |
|---|---|
F | Worst rating — pattern of unresolved complaints, fraud allegations, or refusal to engage with BBB |
NR | Not Rated — insufficient information or business too new |
Accreditation vs. Rating
The two are independent: a business can be A+ and not accredited (didn't apply / didn't pay) or B- and accredited (passed standards review even with mixed complaint history). Use both bbbRating and isAccredited to score risk.
Use Cases
B2B Lead Generation (Local Services)
Companies selling into the trades — software vendors, payment processors, lead-gen networks, equipment suppliers, insurance brokers — use BBB as a curated source of vetted local-service businesses:
- Pull every roofing contractor in Dallas-Fort Worth with rating ≥
A-for a SaaS roofing CRM sales push - Build a HVAC TAM list for every metro you target by running 20+ keyword × city pairs in one schedule
- Enrich CRM accounts (Salesforce, HubSpot, Pipedrive, Close) with BBB rating, accreditation, complaint counts, and owner name
- Filter outbound to accredited businesses only by setting
accreditedOnly: true— instantly higher reply rates because the prospects have already paid to be vetted - Score lead quality in your scoring model using
complaintsLast3Yrs / yearsInBusinessas a normalized friction signal - Route territory by ZIP using the
zipCodeandcityfields exactly as they appear on BBB - Tier accounts —
A+accredited & 10+ years in business → enterprise team;Brated & <3 years → SMB self-serve
Business Credit & Risk Analysis
Trade-credit insurers, factoring companies, BNPL providers, alt-data scoring shops, and KYB platforms use BBB data as a soft-but-pervasive trust signal:
- Build a daily watchlist of every counterparty in your portfolio and re-pull BBB to detect rating downgrades
- Flag spikes in
complaintsLast12Moas an early-warning signal of operational distress - Combine with SAM.gov, TTB and state licensing data to build a multi-source trust score
- Validate ownership during onboarding by cross-referencing
ownerNameagainst operating-agreement filings - Detect newly accredited businesses in your target ICP for credit upsells
- Quantify reputation tail risk by joining
bbbRating×complaintsTotal×governmentActionsinto a single score - Provide adverse-media surrogate for borrowers without traditional bureau coverage
Reputation Monitoring & Brand Protection
Brands, franchise HQs, and managed-service providers use this actor to watch their own and competitor reputation:
- Monitor every franchise location of a multi-location brand for rating drops, new complaints, or accreditation lapses
- Diff weekly snapshots to catch new complaints within 7 days of filing
- Benchmark against competitors in the same metro and category
- Trigger PR / customer-care workflows when
complaintsLast12Mocrosses a threshold - Audit franchisee compliance with brand standards by tracking license numbers and
governmentActions - Feed Power BI dashboards that show rating drift per location per month
M&A Due Diligence (Lower-Middle-Market Services Roll-Ups)
PE firms and search funds rolling up local services (HVAC, plumbing, roofing, pest control, auto repair, vet clinics, home health) lean on BBB as a free, pre-acquisition diligence layer:
- Screen targets in a metro by pulling every
AandA+rated business in the trade - Reject targets with
Fratings orgovernmentActionscontent before spending hours on a CIM - Quantify complaint exposure for any LOI candidate before committing capital
- Verify years in business against seller-provided figures
- Identify the owner / principal for direct cold outreach (LP-funded search funds rely on this heavily)
- Build sector heatmaps showing density and quality of providers per ZIP for thesis building
Journalism, Watchdog & Complaint Investigations
Investigative reporters, consumer-protection columnists, and state attorney-general offices use BBB to surface patterns of consumer harm:
- Identify clusters of high-complaint businesses in a single category and metro (e.g. moving scams, debt-relief mills, solar door-knockers, timeshare exit firms)
- Track government-action narratives across hundreds of businesses to spot serial offenders rebranded under new entities
- Quantify "F"-rated business density by neighborhood for accountability journalism
- Combine with TTB alcohol permittees, SAM.gov entities, and state licensing scrapers to build full corporate-shell maps
- Build a complaint-spike alert that fires when any local business breaches a threshold
Contractor & Vendor Vetting
Property managers, REITs, facility managers, insurance adjusters, and corporate procurement teams use BBB during contractor selection:
- Pre-approve vendors by requiring rating ≥
B+andisAccredited === true - Automate panel refresh with a scheduled run every 30 days that re-validates every contractor
- Cross-reference license numbers between BBB and state licensing scrapers (Arizona ROC, NC GC Board, Washington L&I, California DCA) for credentials sanity-check
- Push results to a Make.com / Zapier flow that issues / revokes vendor portal access automatically
- Maintain a per-property "approved trades" list with daily-fresh ratings
Compliance & Anti-Fraud Operations
Marketplaces, payment platforms, and KYB-driven onboarding teams use BBB data as one signal among several:
- Block onboarding for merchants with
Fratings or activegovernmentActions - Manual review queue triggered by
complaintsLast12Mo > N - Risk segmentation for chargeback monitoring — high-rating accredited merchants get faster settlement
- Build merchant-risk profiles that combine BBB with SAM.gov debarment, OFAC, and state licensing scrapes
- Post-incident retro — diff the BBB snapshot from before vs. after a chargeback storm
Market Research & Competitive Intelligence
Strategy consultants, market-research firms, and corporate strategy teams use the dataset to size local-service markets:
- Count active accredited businesses per category per metro to size TAM
- Track competitor counts over time (run the same query monthly, diff the dataset)
- Map rating distribution — what percentage of plumbers in Atlanta are
A-rated vs.Bvs. unaccredited? - Quantify market consolidation by tracking owner-name uniqueness over many businesses
- Geographic expansion modeling — pull 50 metros in one schedule, normalize, plot rating × density
Insurance Underwriting (Small Commercial)
Carriers underwriting GL, BOP, E&O, or workers-comp for small contractors use BBB as a free underwriting overlay:
- Auto-decline quotes for
F-rated applicants - Surcharge quotes where
complaintsLast3Yrs > 5 - Validate years in business during quote bind
- Re-check at renewal — schedule a monthly refresh against your in-force book
Academic & Public-Policy Research
Researchers studying small-business dynamics, consumer protection, and local labor markets use BBB as a free, structured panel:
- Study churn by snapshotting the dataset quarterly and comparing
- Analyze complaint patterns across demographics and ZIP codes
- Quantify accreditation impact on consumer-review volume
- Compare US vs. Canadian business norms by running both
country: "USA"andcountry: "CAN"
Sample Queries & Recipes
Recipe 1 — Top-rated roofing contractors in Texas metros (lead-gen TAM)
{"searchUrls": ["https://www.bbb.org/search?find_text=roofing+contractor&find_loc=Houston%2C+TX&find_country=USA","https://www.bbb.org/search?find_text=roofing+contractor&find_loc=Dallas%2C+TX&find_country=USA","https://www.bbb.org/search?find_text=roofing+contractor&find_loc=Austin%2C+TX&find_country=USA","https://www.bbb.org/search?find_text=roofing+contractor&find_loc=San+Antonio%2C+TX&find_country=USA"],"accreditedOnly": true,"sort": "Rating","scrapeDetails": true,"maxResults": 0,"maxPages": 10,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Recipe 2 — HVAC TAM across the southwest US (no detail enrichment for speed)
{"keyword": "HVAC","location": "Arizona","country": "USA","scrapeDetails": false,"maxResults": 500,"maxPages": 25}
Recipe 3 — Canadian general contractors in Greater Toronto
{"keyword": "general contractor","location": "Toronto, ON","country": "CAN","accreditedOnly": false,"scrapeDetails": true,"maxResults": 200}
Recipe 4 — High-risk movers nationwide (journalism / consumer protection)
{"keyword": "moving company","location": "United States","country": "USA","sort": "Rating","scrapeDetails": true,"maxResults": 1000,"maxPages": 50}
Then post-filter in your stack:
high_risk = [r for r in recordsif r["bbbRating"] in ("F", "D-", "D", "D+")or (r.get("complaintsLast12Mo") or 0) > 5]
Recipe 5 — Reputation watch for a specific brand's franchise network
{"keyword": "ABC Plumbing","location": "United States","country": "USA","scrapeDetails": true,"maxResults": 0,"maxPages": 20}
Schedule this nightly; diff bbbRating and complaintsLast12Mo against yesterday's run.
Recipe 6 — Test sample (10 records to validate filters before a big run)
{"keyword": "electrician","location": "90210","country": "USA","scrapeDetails": true,"maxResults": 10,"maxPages": 1}
Recipe 7 — Auto-dealer vetting with full enrichment in Chicago
{"keyword": "used car dealer","location": "Chicago, IL","country": "USA","accreditedOnly": true,"sort": "Rating","scrapeDetails": true,"maxResults": 300,"maxPages": 15,"requestDelay": 3000,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Integration Examples
Google Sheets
- Create an Apify schedule that runs this actor once a week with your TAM keywords
- Add the "Save to Google Sheets" Apify integration to the schedule
- Every Monday morning, a fresh sheet of BBB-vetted leads appears in your Drive — append-mode keeps history
Make.com / Zapier / n8n
The Apify connector exists on every major automation platform. Common BBB triggers:
- New A+ accredited business in $METRO → push to Slack
#saleschannel - Rating downgrade for any account in CRM → create a HubSpot Task for the account owner
complaintsLast12Mospike → email the customer-success team- New
governmentActionstext → page the compliance officer
Power BI / Tableau / Looker
Pull the Apify dataset via the REST API as a custom data source. Refresh on the actor's schedule. Dashboards we have seen built on this data:
- Rating distribution heatmap per metro per category
- Complaint velocity (
complaintsLast12Mo / yearsInBusiness) per ZIP - Accredited vs. non-accredited share over time
- Top 20 worst-rated businesses per state, refreshed weekly
Postgres / Snowflake / BigQuery
Use Apify's webhook integration to POST the dataset URL to your warehouse ingestion endpoint after every run. The flat JSON schema maps cleanly to a single bbb_businesses table; treat bbbId as a natural key for upserts.
CREATE TABLE bbb_businesses (bbb_id TEXT PRIMARY KEY,business_name TEXT,bbb_rating TEXT,is_accredited BOOLEAN,accreditation_since TEXT,city TEXT,state TEXT,zip_code TEXT,phone TEXT,website TEXT,categories TEXT[],years_in_business INTEGER,owner_name TEXT,complaints_total INTEGER,complaints_3yrs INTEGER,complaints_12mo INTEGER,review_count INTEGER,avg_review_rating NUMERIC(2,1),scraped_at TIMESTAMPTZ);
Salesforce / HubSpot / Pipedrive CRM Enrichment
Trigger a scheduled run nightly, then upsert against Account records keyed on bbbId (preferred) or website (fallback). Rating-change events can create Tasks, fire Workflows, or update Lead Scores automatically.
Webhook fan-out
Apify can POST the run's dataset directly to any HTTPS endpoint. Use this to push fresh BBB data into your own backend, a Lambda, a Cloud Function, or a worker queue without polling.
Major US & Canadian Markets Covered
BBB lists businesses in every metro across the United States and Canada. The table below highlights the markets most commonly queried by users of this actor — but the actor works for any city or postal code BBB indexes.
| Market | Country | Why this metro shows up so often |
|---|---|---|
| New York, NY | USA | Largest small-business pool in the US; high inbound from B2B SaaS teams |
| Los Angeles, CA | USA | Massive home-services TAM; contractor due diligence |
| Chicago, IL | USA | Strong financial services + trades coverage |
| Houston, TX | USA | Energy services, HVAC, roofing — high storm-claim volume |
| Dallas–Fort Worth, TX | USA | Default keyword + location for trades lead-gen |
| Phoenix, AZ | USA | HVAC capital of the US; pairs cleanly with the Arizona ROC scraper |
| Atlanta, GA | USA | Logistics, moving, home services — high complaint-investigation use |
| Miami, FL | USA | Real estate services, hurricane-zone contractors |
| Seattle, WA | USA | Pairs with the Washington L&I contractor scraper |
| Denver, CO | USA | Pairs with the Colorado professional license scraper |
| Boston, MA | USA | Professional services, education-adjacent |
| Washington, DC | USA | Government-services adjacent companies |
| Toronto, ON | CAN | Largest Canadian metro; default country: "CAN" test |
| Vancouver, BC | CAN | West-coast trades + property management |
| Montréal, QC | CAN | French-language listings still parse cleanly |
| Calgary, AB | CAN | Energy services + home builders |
| Ottawa, ON | CAN | Federal-services adjacency |
| Edmonton, AB | CAN | Trades, contractors |
The country input toggles between USA and CAN; the location input accepts city + state/province, state/province alone, or ZIP / postal code.
Cost & Performance
| Metric | Value |
|---|---|
| Engine | Playwright Chromium (headed mode under xvfb) + Cheerio |
| Auth required | None (no BBB account, no API key) |
| Proxy required | Recommended for production runs (RESIDENTIAL group) |
| Concurrency | Default 1; max 3 — BBB rate-limits aggressively |
| Memory footprint | 1024 MB minimum, 4096 MB cap (browser overhead) |
| Search-only runtime | ~5–10 seconds per 20-result page |
| Detail-enriched runtime | ~5–10 seconds per business profile (add requestDelay) |
| Data freshness | Live at run time — exactly what BBB serves the moment you scrape |
| Pricing model | Pay-per-event (transparent per-record pricing) |
| Cost per 100 search-only records | typically pennies |
| Cost per 100 fully enriched records | varies with requestDelay and proxy use |
| Output formats | JSON, CSV, Excel, HTML, XML, RSS, JSON Lines |
Tuning tip: if you only need name + rating + accreditation + city for lead scoring, leave
scrapeDetails: false. You will get 20× the throughput. Flip totrueonly for the high-value records you actually need to enrich.
Compliance, Privacy & Legal Notes
- Public data only — every field this actor returns is published on
www.bbb.organd visible to any visitor without login - No PII beyond business listings —
ownerNameis the public principal contact the business itself filed with BBB - No PHI — BBB is a business directory, not a healthcare system; no patient data is in scope
- No SSNs, DOBs, or financial credentials are extracted or available
- Email addresses are pulled from publicly displayed
mailto:links and Cloudflare-obfuscateddata-cfemailattributes that BBB has chosen to display; share-linkmailto:?body=URLs are explicitly filtered out - Robots & ToS — review BBB's Terms of Use before commercial redistribution of the data; the actor is provided as a self-service tool for the operator to use within those terms
- Rate limits — the actor's default
requestDelayandmaxConcurrencyare intentionally conservative to minimize load on BBB's infrastructure - GDPR / CCPA / CASL — compliance with downstream marketing, telemarketing, and email regulations (CAN-SPAM, TCPA, CASL, GDPR) is the responsibility of the data consumer; BBB profile contact info is not consent to be marketed to
- No bulk redistribution of BBB's proprietary rating methodology is intended; the actor surfaces the rating value, not BBB's underlying algorithm
- Compliance use cases are explicitly supported — vendor onboarding, KYB, and risk monitoring are well within reasonable commercial use of public directory data
Important: BBB data may not be used for unlawful purposes including identity fraud, stalking, harassment, or coordinated review manipulation. Use the data as a trust signal, not as a substitute for direct due diligence.
Frequently Asked Questions
How fresh is the data?
Live at run time. Every record reflects exactly what BBB.org was serving at the moment the actor scraped it. There is no cache layer between you and BBB — if a rating changed an hour ago, the next run reflects it.
Does the actor handle BBB's Cloudflare protection?
Yes. That is the single biggest technical lift this actor solves. It launches a real Chromium browser in headed mode under Apify's xvfb display, applies stealth init scripts (navigator.webdriver = undefined, window.chrome.runtime stub), and waits up to 30 seconds per page for the Cloudflare challenge to clear before extracting HTML.
Do I need a BBB account or API key?
No. BBB does not publish a public API. This actor scrapes the public website that any visitor can browse, without login.
Do I need proxies?
For small runs (under ~30 businesses) you can run without proxies and usually succeed. For anything larger, or for production reliability, residential proxies are strongly recommended. Pass proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ["RESIDENTIAL"] } in your input.
How many records will I get per run?
You control it with maxResults (default 100, set 0 for unlimited) and maxPages (default 10, each page = ~20 results). BBB's own pagination caps deep results in any single query; if you need very large datasets, split the query across multiple searchUrls (different keyword × location pairs).
Does this work for Canada?
Yes. Set country: "CAN" and pass a Canadian location (e.g. "Toronto, ON", "Vancouver, BC", "Montréal, QC"). The actor follows BBB's find_country=CAN URL pattern automatically.
Does it scrape BBB complaints in full text?
It extracts complaint counts — total, last-3-years, last-12-months, resolved — directly from the profile page. Full complaint narratives are not included by default; BBB shows them on separate paginated sub-pages and they fall outside the schema.
Does it include customer reviews?
Review count and average rating are included. Individual review text is not in the dataset schema.
Can I filter to BBB Accredited businesses only?
Yes — set accreditedOnly: true and the actor drops any listing that explicitly marks "Not BBB Accredited".
How do I sort by rating?
Set sort: "Rating". Other valid values are Relevance (default), Distance, and Name.
Can I run multiple keyword × location queries in one run?
Yes — provide an array in searchUrls. Each URL is walked independently up to maxPages and the results are merged into a single dataset.
Can I use this on the Apify Free Plan?
Yes — every feature works on the free tier. Test with maxResults: 5 to validate your filters before committing to a larger run.
Can I schedule it?
Yes. Apify's built-in Scheduler supports any cron expression. Common schedules:
- Daily watchlist refresh for your CRM accounts
- Weekly TAM rebuild for your territory teams
- Monthly competitor delta diff
Does the actor deduplicate across pages?
Yes. The actor maintains an internal Set keyed on the canonical profile URL and drops duplicates as they appear. Sub-pages (/details, /customer-reviews, etc.) are stripped down to the canonical profile before deduping.
Will it pick up paid ad listings?
No. Search-card links that route through doubleclick.net, adclick, or googleads are filtered out before reaching the dataset.
What if a profile is missing some fields?
The schema is stable — fields that aren't present on a given profile come back as null. This makes downstream ingestion (warehouse, CRM, BI) trivial because the column set never changes between runs.
Why is maxConcurrency capped at 3?
BBB rate-limits aggressively. Running more than 1–3 concurrent browser pages from the same IP almost always triggers temporary blocks. The actor's design favors single-thread + jittered delay + residential proxies over raw parallelism.
Are NAICS codes included?
Not directly — BBB exposes business categories as free text, not NAICS. The categories field is an array of those category strings, which you can map to NAICS in your downstream pipeline.
Can I export to CSV?
Yes — JSON, CSV, Excel, HTML, XML, RSS, and JSON Lines are all available from the Apify dataset view or the dataset items endpoint.
How do I report a bug or request a feature?
Open an issue on the Apify Store actor page or contact the developer directly through the Apify Console. PRs welcome via the Apify version sync.
Related Apify Actors by Haketa
BBB data is most powerful when joined to other public-business datasets. These sibling actors are commonly used alongside this one for B2B lead generation, KYB, contractor vetting, compliance monitoring, and journalism workflows:
- 🇺🇸 SAM.gov Federal Contractor Entity Scraper — every entity registered to do business with the US federal government, with UEI, CAGE, NAICS, debarment status
- 🇺🇸 TTB Alcohol Permittee Scraper — every federally licensed wholesaler, importer, manufacturer of alcoholic beverages
- 🇺🇸 Texas Pharmacy License Scraper — TSBP — every pharmacist, pharmacy, intern, technician licensed in Texas
- 🇺🇸 Arizona ROC Contractor License Scraper — Arizona Registrar of Contractors
- 🇺🇸 Washington L&I Contractor License Scraper — Washington Labor & Industries contractor registry
- 🇺🇸 North Carolina Licensing Board for General Contractors Scraper
- 🇺🇸 California DCA Professional License Scraper — California Department of Consumer Affairs
- 🇺🇸 Colorado Professional License Scraper — Colorado DORA
- 🇺🇸 Virginia DPOR Professional License Scraper — Virginia regulated occupations
- 🇺🇸 Ohio eLicense Scraper — Ohio professional licenses
- 🇺🇸 Illinois IDFPR License Scraper — Illinois Department of Financial and Professional Regulation
- 🇺🇸 Minnesota DLI Professional License Scraper — Minnesota Department of Labor and Industry
Pattern: pull a BBB dataset for a category + metro, then enrich with the matching state-licensing actor on licenseNumbers or ownerName, then enrich with SAM.gov on entity name. You get a three-source view of every business in your TAM — public reputation (BBB) + regulatory licensure (state board) + federal contracting (SAM.gov) — in three actor runs.
Comparison vs. Alternatives
| Approach | Setup time | Handles Cloudflare | Schema normalization | Cost per 1K records | Compliance log |
|---|---|---|---|---|---|
| This actor | < 1 minute | ✅ Built-in headed Playwright + stealth + CF wait loop | ✅ Flat JSON, stable columns | Pennies on pay-per-event | ✅ Automatic |
| Manual BBB browsing | Hours per session | ✅ Human user | ❌ Copy/paste hell | Free + your hourly rate | ❌ None |
requests / axios script | 1 hour to fail | ❌ 403 from Cloudflare | DIY | Free + your time | ❌ None |
| Headless Puppeteer / Playwright DIY | 2–3 days to MVP, ongoing | ⚠️ Partial — easily detected without xvfb tricks | DIY | Infra + dev time | ❌ None |
| Paid "BBB data" reseller | Days of contracting | ✅ | ✅ | $500–2,000+/mo + per-record | Varies |
| BBB partner API | Sales cycle | ✅ | ✅ | Enterprise pricing only | ✅ |
Why Pay-Per-Event Pricing?
Most scraping tools charge a flat monthly subscription (you pay even if you don't use it) or per-Compute-Unit (unpredictable). This actor uses pay-per-event, which means:
- ✅ You only pay when the actor runs and produces records
- ✅ Charges scale with how much BBB data you actually consume
- ✅ Transparent, line-item billing inside Apify
- ✅ No monthly minimums and no seat licenses
- ✅ Free to evaluate — sample with
maxResults: 5for pennies - ✅ Predictable unit economics that map directly to your lead cost or risk-monitoring budget
Changelog
| Version | Date | Notes |
|---|---|---|
| 1.0 | 2026-05 | Initial public release — headed Playwright + Cloudflare bypass, USA + Canada coverage, search-card and full-detail extraction, BBB rating + accreditation + complaints + reviews + owner + license numbers + social media, pay-per-event pricing |
Keywords
BBB scraper · Better Business Bureau data · Better Business Bureau scraper · BBB.org scraper · BBB business profile API · BBB API alternative · BBB data extraction · BBB rating extractor · BBB accreditation scraper · BBB accredited business data · BBB complaints data · BBB complaint counts scraper · BBB reviews scraper · BBB owner lookup · BBB license number scraper · BBB lead generation · B2B business directory scraper · contractor reputation lookup · contractor vetting API · roofing contractor leads BBB · HVAC leads BBB · plumber leads BBB · electrician leads BBB · auto dealer reputation lookup · moving company complaints scraper · BBB letter grade scraper · A+ accredited business scraper · BBB rating downgrade alert · KYB enrichment BBB · vendor onboarding BBB · BBB Canada scraper · BBB USA scraper · BBB Toronto scraper · BBB Dallas scraper · BBB Houston scraper · BBB Phoenix scraper · BBB Los Angeles scraper · BBB New York scraper · BBB Chicago scraper · BBB Atlanta scraper · BBB Miami scraper · small business credit signal · business reputation monitoring API · reputation monitoring scraper · M&A due diligence small business · investigative journalism BBB data · consumer protection data · franchise reputation monitoring · multi-location brand monitoring BBB · Apify BBB actor · Playwright Cloudflare bypass scraper · headed Chromium BBB scraper · BBB scheduled scraper
Support
- 🐛 Bug reports: Use the Issues tab on the Apify Store actor page
- 💡 Feature requests: Same place — please describe your use case so we can prioritize
- 📧 Direct contact: Through the Apify developer profile
If this actor saves you time, a 5-star rating on the Apify Store helps other B2B, compliance, journalism, and reputation-monitoring teams discover it. Thank you!