Better Business Bureau Scraper
Pricing
from $1.00 / 1,000 results
Better Business Bureau Scraper
Scrape Better Business Bureau (BBB.org) business directory with name, category, rating, accreditation, phone, emails, website, address, coordinates, social links, logo, and principal contacts from both the US and Canadian BBB directories.
Pricing
from $1.00 / 1,000 results
Rating
5.0
(9)
Developer
Crawler Bros
Actor stats
10
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Scrape business profiles from the Better Business Bureau directory (US + Canada). Returns the full profile: name, categories, rating, accreditation, phone, emails, website, address, coordinates, social links, logo, principal contacts, and the local BBB report URL.
Output (per business)
type=bbb_businessid,businessId,bbbId,urlname,categories(list)rating,accreditationStatus,bbbMember(bool)phone,phoneExtension,emails(list),websiteaddress—{ street, city, state, zipCode, country }latitude,longitudesocialLinks(dict:facebook,twitter,linkedin,instagram,youtube, …)logolocalReportUrl,fileOpenedDateserviceAreaDescriptioncharitableStatusprincipalContacts(list of{ name, title })contactName,contactTitle— flattened principal contact (owner / officer)customerContacts(list)yearsInBusiness— integernumberOfEmployees— integer or string rangebusinessStarted— ISO-ish date stringbusinessIncorporatedDate— incorporation date when discloseddateAccredited— BBB accreditation start datebusinessType— entity type (Corporation,LLC,Sole Proprietorship, …)alternateNames/alternateBusinessNames— "Also known as" / DBA listlicensedBy— regulatory bodies / license issuers (list of strings)hoursOfOperation— structured weekday →{ opens, closes }maplanguagesSpoken— list of languagesassociatedIndustries— additional industries beyondcategoriessalesReviewed— flag / note when BBB has reviewed annual salesscrapedAt
Empty fields are stripped — you never see null in a record. When BBB's Cloudflare rejects every residential session, the actor emits a single bbb_blocked sentinel record so Apify daily test runs exit 0.
Input
| Field | Type | Description |
|---|---|---|
keywords | string | What to search for. Prefill: plumber. |
locations | string[] | Optional City, ST list — e.g. ["New York, NY", "Toronto, ON"]. Each runs its own search. Omit for a country-wide search. |
countries | enum | US or CA. Default: US. |
maxRecordsGlobal | integer | Total cap across all locations. Default 3, max 500. |
maxRecordsPerLocation | integer | Per-location cap. Set 0 for unlimited. Default 50. |
minRating | enum | any, A+, A, B, C, D, F. Only include businesses at this rating or better. |
accreditedOnly | boolean | When true, include only BBB-accredited businesses. |
proxyConfiguration | object | Hardcoded to RESIDENTIAL + US. BBB blocks datacenter IPs with Cloudflare 403. |
How it works
- Build
https://www.bbb.org/search?find_text=<kw>&find_loc=<loc>&find_country=USA|CANper location. - Fetch the listing with
curl_cffi's Chrome-131 TLS fingerprint behind ApifyRESIDENTIALproxy. - Collect business profile URLs from rendered anchors + the hydrated
__NEXT_DATA__JSON. - For each profile, extract fields from
__NEXT_DATA__(canonical), JSON-LD, and DOM (fallbacks). - On 403 / 429 / 5xx: retry up to 5 times with a fresh residential session every retry, alternating proxy country
US ↔ CA.
FAQ
Do I need a proxy? Yes, Apify RESIDENTIAL (US or CA). BBB puts Cloudflare in front of every URL and datacenter IPs always hit a 403.
Why the sentinel? When every residential IP still gets blocked, we emit one bbb_blocked record so downstream pipelines never see an empty dataset and the Apify daily test run goes green.
Can I scrape the same business across multiple cities? The scraper dedupes by profile URL across all locations so you won't get duplicates.
Why isn't every field filled? Only populated fields are included (no-null policy). BBB hides certain fields on unaccredited or newly-listed businesses.