# BBB Business Directory Scraper (`scrapeworks/bbb-business-directory-scraper`) Actor

Scrape business listings from the Better Business Bureau (bbb.org) in bulk: name, category, full address, phone, geo, BBB letter rating and accreditation status. Search by category and location across the US, Canada and Mexico. Build local B2B lead lists and directories.

- **URL**: https://apify.com/scrapeworks/bbb-business-directory-scraper.md
- **Developed by:** [Nicolas van Arkens](https://apify.com/scrapeworks) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## BBB Business Directory Scraper

Extract business listings from the **Better Business Bureau** (bbb.org) directory in
bulk. Search by category and location and get one clean row per business — name,
category, full address, phone, geo coordinates, BBB letter rating, accreditation
and a link to the full BBB profile. Perfect for building **local B2B lead
lists**, contractor and service-provider directories, or market research on any
trade in any US, Canadian or Mexican city.

No login, API key or browser automation required. Every BBB search page ships its
results as structured data, so this scraper returns clean, consistent JSON — not
brittle screen-scraped text.

### What you get (one row per business)

| Field | Description |
|---|---|
| `businessName` | Company name as listed on BBB |
| `primaryCategory` | Main line of business (e.g. "Plumber", "Roofing Contractor") |
| `categories` | All categories the business is listed under |
| `bbbRating` | BBB letter rating (`A+`, `A`, `B`, … `F`, or `NR`) |
| `ratingScore` | Numeric rating score (0–100) when available |
| `accredited` | `true` if the business is BBB Accredited |
| `outOfBusinessStatus` | BBB status code when the business is marked out of business; `null` for active businesses |
| `phone` / `phones` | Primary phone plus all listed numbers |
| `streetAddress`, `city`, `state`, `postalCode` | Full mailing address |
| `latitude`, `longitude` | Geo coordinates |
| `serviceAreas` | Service-area summary when the business lists one |
| `profileUrl` | Link to the full BBB business profile |
| `requestQuoteUrl` | BBB "Request a Quote" link when offered |
| `leaveReviewUrl` | BBB "Leave a Review" link |
| `servingBbb` | The local BBB office serving this business |
| `searchTerm`, `searchLocation`, `resultPage` | Which search produced the row |
| `scrapedAt` | UTC timestamp of the scrape |

### Input

Give it **arrays** — every search term is run against every location (a cross
product), and each search is paginated deep. So 5 terms × 4 cities = 20 searches
in a single run.

```json
{
  "searchTerms": ["plumber", "roofing contractor"],
  "locations": ["New York, NY", "Los Angeles, CA", "Chicago, IL"],
  "country": "USA",
  "maxResultsPerSearch": 225,
  "accreditedOnly": false,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }
}
````

- **searchTerms** — categories (`plumber`, `hvac`, `auto repair`, `dentist`) or a
  specific company name. Add as many as you like.
- **locations** — `City, ST`, a state, or a ZIP code. Leave empty to search each
  term nationally (a location is recommended for category searches).
- **country** — `USA`, `CAN`, or `MEX`.
- **maxResultsPerSearch** — cap per term+location pair. BBB caps a single search at
  \~225 businesses (15 pages), so `225` pulls everything for that search; use more
  locations to cover a whole region.
- **accreditedOnly** — set `true` to keep only BBB-Accredited businesses.
- **searchUrls** (power users) — paste full bbb.org `/search` URLs with your own
  filters already applied; each is scraped and paginated just like a term+location.

### Output sample

```json
{
  "businessId": "87144493",
  "businessName": "Daniel's Plumbing Services",
  "primaryCategory": "Plumber",
  "categories": ["Plumber", "Plumbing Renovation", "Sewer Cleaning"],
  "bbbRating": "A+",
  "ratingScore": 100,
  "accredited": true,
  "phone": "(212) 369-2500",
  "phones": ["(212) 369-2500"],
  "streetAddress": "397 Lexington Ave.",
  "city": "New York",
  "state": "NY",
  "postalCode": "10016",
  "latitude": 40.75146484375,
  "longitude": -73.97583007812499,
  "serviceAreas": ["New York County, NY"],
  "profileUrl": "https://www.bbb.org/us/ny/new-york/profile/plumber/daniels-plumbing-services-0121-87144493",
  "servingBbb": "BBB Serving Metropolitan New York",
  "searchTerm": "plumber",
  "searchLocation": "New York, NY",
  "resultPage": 1,
  "scrapedAt": "2026-07-19T00:00:00+00:00"
}
```

### Use cases

- **B2B lead generation** — build targeted lists of local service businesses
  (contractors, plumbers, HVAC, dentists, auto shops) with phone and address, ready
  for outreach or CRM import.
- **Market research** — measure how many businesses compete in a trade + city, and
  how their BBB ratings and accreditation stack up.
- **Data enrichment** — match your own company records to BBB rating, accreditation
  and profile URL for trust/reputation signals.
- **Directory building** — power a niche local-business or "find a pro" directory.

### FAQ

**Do I need a BBB account or API key?** No. The scraper reads public search pages.

**How many businesses can I get per search?** BBB caps a single category+location
search at about 225 businesses (15 pages of 15). To pull an entire metro or state,
run the same term across several locations (neighborhoods, cities, ZIP codes).

**Which countries are covered?** United States (`USA`), Canada (`CAN`) and Mexico
(`MEX`).

**Why use a proxy?** BBB's CDN can throttle datacenter traffic at volume. The actor
defaults to Apify Residential proxy (US) and automatically rotates to a fresh session
if a page is blocked, so large runs stay reliable.

**How is it billed?** Pay per result — you're charged once for each business row the
actor returns. Blocked or empty pages are never charged.

# Actor input Schema

## `searchTerms` (type: `array`):

One or more things to search for on bbb.org - a business category like 'plumber', 'roofing contractor', 'hvac', 'auto repair', or a specific company name. Every search term is run against every location below (so 5 terms x 4 locations = 20 searches), and each search is paginated deep. Results are billed per business row, so more terms = more rows.

## `locations` (type: `array`):

Locations to search in - 'City, ST' (e.g. 'New York, NY'), a state, or a ZIP code. Each search term is searched in each location. Leave empty to search each term nationally (a location narrows results and is recommended for category searches). The BBB caps a single location search at about 225 businesses, so use several locations to pull a whole region.

## `searchUrls` (type: `array`):

Optional: paste full bbb.org search-results URLs (e.g. 'https://www.bbb.org/search?find\_country=USA\&find\_text=plumber\&find\_loc=New%20York%2C%20NY') with your own filters already applied. Each URL is scraped and paginated deep, just like a term+location pair. Use this when you want BBB's own advanced filters; otherwise just use Search terms + Locations.

## `country` (type: `string`):

Country to search within. USA = United States, CAN = Canada, MEX = Mexico. Applied to the Search terms + Locations searches (not to pasted Search URLs, which carry their own country).

## `maxResultsPerSearch` (type: `integer`):

Maximum businesses to return for EACH term+location pair (and each pasted URL). The actor paginates automatically (15 businesses per page). The BBB itself caps a single search at about 225 results, so a value of 225 pulls everything available for that search.

## `accreditedOnly` (type: `boolean`):

If enabled, only businesses that are BBB Accredited are returned (and billed). Leave off to get every business the directory lists, accredited or not.

## `proxyConfiguration` (type: `object`):

Proxy used to reach bbb.org. The default (Apify Residential proxy, US) is recommended - the site's CDN can throttle datacenter traffic at volume. The actor automatically rotates to a fresh proxy session if a page is blocked.

## Actor input object example

```json
{
  "searchTerms": [
    "plumber",
    "roofing contractor",
    "hvac"
  ],
  "locations": [
    "New York, NY",
    "Los Angeles, CA",
    "Chicago, IL"
  ],
  "searchUrls": [
    "https://www.bbb.org/search?find_country=USA&find_text=electrician&find_loc=Austin%2C%20TX"
  ],
  "country": "USA",
  "maxResultsPerSearch": 225,
  "accreditedOnly": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "plumber"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapeworks/bbb-business-directory-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["plumber"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapeworks/bbb-business-directory-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "plumber"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call scrapeworks/bbb-business-directory-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapeworks/bbb-business-directory-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "BBB Business Directory Scraper",
        "description": "Scrape business listings from the Better Business Bureau (bbb.org) in bulk: name, category, full address, phone, geo, BBB letter rating and accreditation status. Search by category and location across the US, Canada and Mexico. Build local B2B lead lists and directories.",
        "version": "0.1",
        "x-build-id": "yjVHiZWRfsVjf3q3O"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapeworks~bbb-business-directory-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapeworks-bbb-business-directory-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/scrapeworks~bbb-business-directory-scraper/runs": {
            "post": {
                "operationId": "runs-sync-scrapeworks-bbb-business-directory-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/scrapeworks~bbb-business-directory-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-scrapeworks-bbb-business-directory-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchTerms": {
                        "title": "Search terms (category or business name)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "One or more things to search for on bbb.org - a business category like 'plumber', 'roofing contractor', 'hvac', 'auto repair', or a specific company name. Every search term is run against every location below (so 5 terms x 4 locations = 20 searches), and each search is paginated deep. Results are billed per business row, so more terms = more rows.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "locations": {
                        "title": "Locations",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Locations to search in - 'City, ST' (e.g. 'New York, NY'), a state, or a ZIP code. Each search term is searched in each location. Leave empty to search each term nationally (a location narrows results and is recommended for category searches). The BBB caps a single location search at about 225 businesses, so use several locations to pull a whole region.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchUrls": {
                        "title": "BBB search URLs (optional, power users)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Optional: paste full bbb.org search-results URLs (e.g. 'https://www.bbb.org/search?find_country=USA&find_text=plumber&find_loc=New%20York%2C%20NY') with your own filters already applied. Each URL is scraped and paginated deep, just like a term+location pair. Use this when you want BBB's own advanced filters; otherwise just use Search terms + Locations.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "Country",
                        "enum": [
                            "USA",
                            "CAN",
                            "MEX"
                        ],
                        "type": "string",
                        "description": "Country to search within. USA = United States, CAN = Canada, MEX = Mexico. Applied to the Search terms + Locations searches (not to pasted Search URLs, which carry their own country).",
                        "default": "USA"
                    },
                    "maxResultsPerSearch": {
                        "title": "Max results per search",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum businesses to return for EACH term+location pair (and each pasted URL). The actor paginates automatically (15 businesses per page). The BBB itself caps a single search at about 225 results, so a value of 225 pulls everything available for that search.",
                        "default": 225
                    },
                    "accreditedOnly": {
                        "title": "BBB-accredited businesses only",
                        "type": "boolean",
                        "description": "If enabled, only businesses that are BBB Accredited are returned (and billed). Leave off to get every business the directory lists, accredited or not.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy used to reach bbb.org. The default (Apify Residential proxy, US) is recommended - the site's CDN can throttle datacenter traffic at volume. The actor automatically rotates to a fresh proxy session if a page is blocked.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "US"
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
