BBB Business Scraper

The directory,
as a spreadsheet.

Type a trade - or paste a BBB category or search URL - and the businesses come back as rows: the name, BBB's letter grade, whether they are accredited, their categories, address, phone, email, website and how long they have been trading.

one-time 500 free rows$0.002 per row afterone row per businessCSV · JSON · Excel
How it works

Three ways to ask,
one box.

There is no sort control on this one. What shapes the run is what you type and how much of it you want.

  1. STEP 1Sign in to the platform.
  2. STEP 2Open the BBB Business Scraper.
  3. STEP 3Enter a plain search term such as auto sellers, a category URL like bbb.org/us/category/…, or a full bbb.org/search?… URL with the location filters you want - one per line, mixed freely.
  4. STEP 4Or upload a CSV, XLSX, TXT or Parquet file of the same.
  5. STEP 5Set a limit per query if you want one. It takes a minimum of 1, and leaving it empty fetches all - there is no default.
  6. STEP 6Click Start scraping and download as CSV, JSON or Excel.

Building the search URL on bbb.org first is the easy way to pin down a location: whatever filters you set there travel with the URL.

Why it is useful

A grade, a category
and a way to reach them.

Three things this export carries that a general business directory usually does not.

BBB's own grade, and accreditation

rating is the letter grade BBB assigns - a string like A+, not a star score - and accredited says whether the business pays for accreditation. Together they are a filter you cannot build from a map listing: a shortlist of graded, accredited firms in a trade.

Categories at two levels

category is the headline trade and all_categories is the full comma-joined list, which is usually several. A roofing firm that also lists windows and siding shows both - so you can search narrowly and still see everything else they claim to do.

Contact details, where published

Phone, website, address and often an email arrive as separate columns, alongside years_in_business and a named contact. Not every business publishes all of it - see the note below on how this export handles that, because it does not do what you would expect.

Read this first

This export omits keys
rather than emptying them.

It is the one genuinely surprising thing about this service, and it will break naive code. Two minutes here saves an afternoon.

When a business does not publish a field, the column is not blank - it is absent from that row entirely. Across the rows we have read there were dozens of different key sets in a single file. Only a handful of columns appeared on every row: the query, the profile URL, the name, the headline category, the phone, the city, state and postcode, and whether the business is accredited. Everything else comes and goes depending on what that business chose to publish.

For a CSV or Excel download this is invisible - the columns line up and the gaps are empty cells. For the JSON export it matters a great deal. Code that reads row.website and expects a string will get undefined rather than an empty string, and anything that assumes a uniform shape across rows will throw on the first business that keeps its email to itself. Read defensively, or take the spreadsheet format and let it normalise for you.

Two of the declared columns never appeared at all in anything we ran - licenses and social_media. They are part of the service's declared column list, so they may populate for businesses or categories we did not touch, but we have never seen a value in either and so they get no entry in the table below. That is why it lists thirty rather than thirty-two.

One column arrives deliberately mangled. additional_emails carries BBB's own anti-scraping obfuscation - an address appears as something like …finance__at__troysellersauto__dot__com… wrapped in sentinel markers. Every row that has the field is like this, and the plain email column never is. Undoing it is mechanical, but you have to know to do it: strip the markers, turn __at__ into an @ and __dot__ into a dot, and you get the same address the clean column holds.

What you get

Thirty columns,
and formats we measured.

The names are the service's own declared list. The formats were read from real rows. Remember that most of these are absent rather than empty when a business does not publish them.

query
The search term or URL this row came from, echoed onto every row. Present always - group by it when a file covers several searches.
profile_id
BBB's own identifier for the business, as an underscore-joined string. The stable key to match on across runs.
url
The business's BBB profile page. Present on every row - and the place to go for its reviews.
name
The business name as BBB lists it. Present on every row.
type_of_entity
The legal form BBB records - corporation, sole proprietor and so on, including Unknown where it is not established.
contact_information
A named contact with their role, such as Mr Jeff Graves (Owner/Manager). This is a person - see the legal note below.
num_employees
Headcount as a number. One of the rarest fields here: most profiles do not publish it, so expect the key to be missing far more often than not.
primary_category
The headline trade. On every row we read that carried both, this was identical to category.
all_categories
Every category the business lists, as one comma-joined string rather than an array. Usually several, and much wider than the headline one.
category
The headline trade again - the same value as primary_category on every row we have seen. Present on every row, which primary_category is not.
years_in_business
How long they have traded, as a number.
business_start
The founding year, as a string rather than a number - 1992. Worth noting if you are doing arithmetic across both this and years_in_business.
website
The business's own site, where published.
email
A contact address, clean and usable. Only some profiles publish one.
additional_emails
The same kind of address, but obfuscated by BBB - sentinel markers around a form using __at__ and __dot__. Every row that has this field is like that; decode it before use, or prefer email.
phone
The main number, formatted as BBB displays it. Present on every row.
fax_numbers
A fax number where one is listed, formatted the same way.
additional_phone
A secondary number where one is listed.
displayed_address
The full address as one line, the way the profile shows it.
address
Just the street part. Present as a key on every row, though sometimes empty - one of the few that behaves that way rather than being omitted.
city
The city. Present on every row.
state
The state or region code. Present on every row.
postalcode
The postcode, sometimes in the longer ZIP+4 form. Present on every row.
country
The country. Every row we have read said USA, but every search we ran was a US one, so treat that as a property of our runs rather than a limit of the service.
service_area
Where they will travel to, as an array of strings - typically counties, then the state, then the country.
accredited
Whether the business is BBB accredited, as the string Yes or No rather than a boolean. Present on every row.
rating
BBB's letter grade as a string - A+, A, A- and so on. This is BBB's own assessment, not a customer score. Do not confuse it with the star rating on our reviews page, which is a number.
average_rating
The customer star average, as a number from 1 to 5. This is the one that comes from reviewers. Absent on businesses with no reviews.
reviews_total
How many customer reviews the profile has, as a number. On every row we read it appeared together with average_rating - never one without the other.
images
The profile image as a single object with height, width, url and altText - not an array, and altText was null on every row we have seen.

Formats above were measured rather than described. Six exports, every row read: rating a letter-grade string, average_rating a number from 1 to 5 always paired with reviews_total, accredited the string Yes or No, service_area an array, images a single object, all_categories a comma-joined string, and category identical to primary_category on every row that had both. Two things to carry away. First, this export omits keys rather than blanking them, so only a handful of columns are guaranteed present on any given row - read the JSON defensively or take the spreadsheet. Second, the table above lists thirty of the thirty-two declared columns: licenses and social_media never appeared in anything we ran, so rather than describe fields we have never seen carry a value we name them here and leave them out. They may populate for categories we did not touch. Everything we ran was a US search, so coverage elsewhere is not something this page claims either way.

Use cases

Three jobs people
run this for.

All of them start from something you would type into BBB's own search.

Leads

Build a graded shortlist in a trade

Search a category, keep rating and accredited, and you have a list filtered by something a map listing cannot give you - BBB's own assessment. Add years_in_business and you can favour firms with a track record rather than a new profile.

Sales · Lead gen
Diligence

Check a supplier list against the register

Feed in the trades you buy from and match on name and displayed_address. What you get back is grade, accreditation and how long each has traded - and url takes you straight to the profile if a grade prompts a closer look.

Procurement · Risk
Coverage

Map who actually serves an area

service_area is an array of the counties and states a business will travel to, which is a different question from where its office is. For anyone planning territory coverage, that distinction is the whole point.

Ops · Field services
Pricing

Pay per business row,
nothing else.

No subscription, no minimum, no per-seat licence. Your first 500 rows are on us - after that it is pay-as-you-go.

Free

500 rows

For every new account, one time. No credit card. All scrapers unlocked - and enough to run one category and see for yourself which columns turn up and which are simply absent.

One-time · No card
Pay as you go

$0.002 per row

Roughly $2 per 1,000 businesses, the same flat rate as every other scraper on the platform. The limit is per query and has no default, so a broad category with the field left empty can run long - set a small one first.

Credits never expire
Enterprise

Custom - whole categories, on a schedule

Volume pricing, SLAs, dedicated workers and tailored onboarding for teams building a directory rather than a shortlist. Tell us your numbers and we will quote.

Talk to sales
10% off your first paid run.Use code LIVESCRAPER10 at checkout.
Sign up
Pairs well with

The profile,
and what is inside it.

This returns the business. These return what people said about it, and where else it appears.

Legal

Is it legal to scrape
BBB business profiles?

Short answer: these are public business listings - but this export carries more about people than most, and that is worth being deliberate about.

Everything in these columns is shown to any visitor on a public BBB profile, signed in or not. No login is used, no paywall is crossed and no account is touched, and the run goes through our proxy pool rather than your own address. Collecting publicly listed business information for research, lead generation and due diligence is long-settled practice.

Business contact data is not automatically exempt from privacy law. contact_information holds a named individual and their role, and email, phone and additional_phone are ways of reaching a person even when they sit under a company name. A small firm's listed address is often someone's home. Under the GDPR and similar regimes that is personal data, and if you intend to use it for outreach you also have marketing rules to satisfy - the CAN-SPAM Act in the US, PECR and the GDPR in the UK and EU - which are about consent and opt-outs rather than about how you obtained the address.

The additional_emails obfuscation is a signal worth reading honestly: BBB has taken a deliberate step to make that column hard to harvest in bulk. Nothing stops you decoding it, and this page tells you how, but treat it as a reminder to be proportionate - a shortlist you will actually contact is a different thing from a scraped mailing list. BBB's terms govern automated access to their site; read them before you scale. We run no third-party trackers on the data layer, and your exports self-delete after 30 days.

livescraper.app · principles
Public BBB profile pages only
No logins, no paywalls
Named contacts and emails are personal data - marketing rules still apply!
No third-party trackers on the data layer
Exports self-delete (30 days)
The same listings any visitor sees on bbb.org.
FAQ

Things people ask before signing up.

The questions we hear most. Something else? Talk to us - humans write the answers, not bots.

What do I submit?+
Any of three things, mixed freely, one per line: a plain search term such as auto sellers, a BBB category URL like bbb.org/us/category/…, or a full bbb.org/search URL with the location filters you want. Building the search on bbb.org first is the easy way to pin down a place. You can upload a CSV, XLSX, TXT or Parquet file instead of pasting.
Why are some columns missing from a row?+
Because this export omits a key entirely when the business does not publish that field, rather than including it as an empty value. Only a handful are present on every row - the query, profile URL, name, category, phone, city, state, postcode and accreditation. In a CSV or Excel download you will not notice, since the columns line up and the gaps are blank cells. In the JSON export it matters: code that assumes row.website exists will get undefined. Read defensively, or use the spreadsheet format.
Is rating the star score?+
No. Here rating is BBB's own letter grade, a string such as A+ or A-. The customer star average is a separate column, average_rating, which is a number from 1 to 5 and appears alongside reviews_total. This is worth double-checking if you also use our BBB Business Reviews Scraper, because on that page rating means the star score instead.
Why is additional_emails full of strange characters?+
That is BBB's own anti-scraping obfuscation, not damage from our side. The address is wrapped in sentinel markers with __at__ in place of the @ and __dot__ in place of the dots. Every row that has the field looks like that, and the plain email column never does. Strip the markers and swap those two tokens back and you get the same address the clean column holds.
What columns will the export contain?+
The service declares thirty-two: query, profile_id, url, name, type_of_entity, contact_information, num_employees, primary_category, all_categories, category, licenses, years_in_business, business_start, website, social_media, email, additional_emails, phone, fax_numbers, additional_phone, displayed_address, address, city, state, postalcode, country, service_area, accredited, rating, average_rating, reviews_total and images. Two of those - licenses and social_media - never appeared in anything we ran, so we document thirty.
How does the limit work?+
It takes a minimum of 1 and has no default - leaving it empty fetches everything, which the form says in its own hint. It applies per query, so several searches multiply it. A broad category left unlimited can run long, so set a small limit for a first look.
Does it only cover the US?+
We cannot say. Every search we have run was a US one and every row came back with USA in the country column, but that is a property of our runs rather than something we have established about the service. The form's own example includes a find_country parameter, so try the market you care about on the free tier.
What does it cost?+
The first 500 rows on a new account are free and one-time; after that it is $0.002 per row - about $2 per 1,000 - pay-as-you-go with no subscription. Credits do not expire and there is no monthly reset.

Run one category,
and see the gaps.

The quickest way to learn this export is to watch which columns turn up and which are simply absent. Your first 500 rows are free.

Export BBB business profiles as rows

The BBB Business Scraper turns the Better Business Bureau directory into a spreadsheet. You submit a plain search term, a BBB category URL, or a full bbb.org/search URL carrying whatever location filters you set - one per line, mixed freely, or uploaded as a CSV, XLSX, TXT or Parquet file - set a limit if you want one, and each business comes back as a row: the name, BBB's letter grade, whether it is accredited, its categories at two levels, the address broken into parts, phone and fax, website and email, how long it has traded, the service area it covers and a profile image. One row per business, downloadable as CSV, Excel or JSON. There is no sort control on this service; what shapes the run is the query and the limit.

The behaviour to understand before you write any code against this is that the export omits keys rather than emptying them. When a business does not publish a field, that column is absent from the row entirely, and across the rows we have read there were dozens of different key sets inside a single file. Only a handful are present every time: the query, the profile URL, the name, the headline category, the phone, the city, state and postcode, and the accreditation flag. In a CSV or Excel download this is invisible, because the columns line up and the gaps are blank cells. In JSON it is the difference between an empty string and undefined, so read defensively or take the spreadsheet and let it normalise for you.

Two columns carry names that mislead if you skim. rating is BBB's own letter grade - a string such as A+ - and not a customer score; the customer star average is average_rating, a number from 1 to 5 that appears together with reviews_total and only for businesses that have reviews. If you also use our BBB Business Reviews Scraper, note that rating means the star score there, so the same word means two different things across the pair. Elsewhere the formats are consistent and were measured rather than assumed: accredited is the string Yes or No rather than a boolean, service_area is an array of counties and states, images is a single object rather than an array, all_categories is a comma-joined string that is usually much wider than the headline category, and business_start is a year stored as a string while years_in_business is a number.

One column arrives deliberately mangled. additional_emails carries BBB's own anti-scraping obfuscation, with sentinel markers around a form that writes __at__ for the @ and __dot__ for the dots; every row that has the field is like that, and the plain email column never is. Undoing it is mechanical once you know to. Two of the thirty-two declared columns, licenses and social_media, never appeared in anything we ran, so this page documents thirty and says so rather than describing fields it has never seen carry a value. On the legal side these are public business listings, but the export carries a named contact and direct contact details, and a small firm's listed address is often someone's home - treat it as personal data, and remember that using it for outreach brings marketing rules of its own regardless of how you obtained it. Read BBB's terms before you scale. Start free: your first 500 rows cost nothing and need no credit card, then $0.002 per row, flat. See pricing for current rates.