# BizBuySell Franchises for Sale Scraper (`datacach/bizbuysell-franchises-for-sale-scraper`) Actor

Scrape franchise opportunities from BizBuySell. Filter by category, investment range and state, and get franchises with fees, royalties, unit counts and territories.

- **URL**: https://apify.com/datacach/bizbuysell-franchises-for-sale-scraper.md
- **Developed by:** [DataCach](https://apify.com/datacach) (community)
- **Categories:** Automation, Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 franchises

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## BizBuySell Franchises for Sale Scraper

**Scrape the entire BizBuySell franchise directory** and export every franchise opportunity to **JSON, CSV, or Excel** — with the numbers franchise buyers actually compare: **cash required, total investment range, franchise fee, royalty and ad-fund percentages, unit counts by year, and the states each brand is granting territories in.**

### What is BizBuySell Franchises for Sale Scraper?

This Actor is a **BizBuySell franchise scraper** that turns the [BizBuySell franchise directory](https://www.bizbuysell.com/franchise-opportunities/) — roughly **900 active franchise brands** — into a structured dataset you can sort, filter, and analyze. The site lets you browse brands one page at a time but gives you **no export, no sorting by royalty percentage, and no way to compare unit growth** across brands. This Actor does all three.

For every franchise it collects the **full profile page**, not just the summary card: financial requirements, the fee structure broken out by type, up to five years of franchised-versus-company-owned unit history, corporate details, and the complete list of states where the brand is granting territories. **Every input is optional** — click **Start** with no configuration and you get the whole directory.

### What can this BizBuySell franchise data scraper do?

- 🏪 **Scrape every franchise brand** listed on BizBuySell, or a filtered slice of it
- 🔍 **Filter by 28 franchise categories** — Restaurant and Food, Home Services, Child Related, Low Cost Franchises, Veteran's Franchises, and more
- 📍 **Filter by US state** — matched on where the brand grants territories, not where its head office sits
- 💰 **Filter by total investment range** in USD, so you only get brands your capital supports
- 🔤 **Filter by brand name** with a case-insensitive keyword match
- 📊 **Export 31 fields per franchise** to **JSON, CSV, Excel, XML, or HTML**
- 🕒 **Stamp every record** with `extraction_datetime` (ISO-8601 UTC) and `extraction_date` (`mm-dd-yyyy`) so you can diff runs over time
- 🔁 **Resume safely** — the run persists its progress, so a platform migration does not re-emit franchises you already have
- ⚡ **Fast and light** — the Actor talks directly to BizBuySell's listing API instead of driving a browser, so a full directory scrape finishes in about five minutes on 512 MB

Because it runs on the **Apify platform**, you also get **REST API access**, **scheduled runs**, **run monitoring and alerts**, **automatic proxy rotation**, and one-click **integrations with Make, Zapier, Google Sheets, Slack, and webhooks**.

### Free vs. paid plans: what are the limits?

**This is the only difference between plans.** Every filter, every output field, the API, scheduling, and integrations are identical on both. The single thing a paid Apify plan unlocks is **how many franchises one run may collect**.

| Input | 🆓 Free plan | ⭐ Paid plan |
|---|---|---|
| `maxResults` | **Hard cap of 25 franchises** — applied even when set to `0` | **Full range.** `0` = every match (~900 with the default filters) |
| `categories` | No limit | No limit |
| `states` | No limit | No limit |
| `keyword` | No limit | No limit |
| `investmentMin` / `investmentMax` | No limit | No limit |
| `includeInactive` | No limit | No limit |
| All 31 output fields | ✅ Included | ✅ Included |
| API, scheduling, monitoring, integrations | ✅ Included | ✅ Included |

**How the free cap behaves in practice:**

- The cap is **enforced at runtime**, before the first request. When it kicks in, the run log records a warning such as `Free plan detected — limiting the run to 25 franchises` and, if your `maxResults` was higher, `Maximum results lowered from 100 to 25 by the free plan limit.`
- Setting `maxResults` to `0` ("collect everything") **does not bypass the cap** — on the free plan it still stops at 25.
- The cap is **25 franchises per key-value store**, not 25 per fresh run. The Actor persists how many results it has already pushed so that a resumed or restarted run does not re-emit (or re-charge for) items you already received. Running again against the **same** key-value store therefore continues from where it stopped rather than granting another 25; use a **new** key-value store for a clean count.
- If the plan cannot be verified for any reason, the Actor **fails safe and assumes free**. Any paid Apify plan removes the cap entirely.

Twenty-five franchises is enough to see every financial field populated with real data and decide whether the output fits your workflow before scaling up.

### What data does the BizBuySell franchise scraper extract?

Each franchise becomes one dataset record with **31 fields**:

| Field | Description |
|---|---|
| `franchiseId` | BizBuySell's internal franchise ID |
| `name` | Franchise brand name |
| `url` | BizBuySell profile URL |
| `urlStub` | URL slug of the profile |
| `website` | The brand's own franchising site |
| `description` | Brand overview / positioning line |
| `cashRequired` | Liquid cash the franchisor requires |
| `netWorthRequired` | Minimum net worth required |
| `franchiseFee` | Upfront franchise fee |
| `totalInvestmentMin` / `totalInvestmentMax` | Total cost to open one location |
| `fees` | Fee breakdown by type — `franchiseFee`, `royaltyFee`, `advertisingFee`, `other` — each with flat `value`, `percent`, and the `base` it applies to |
| `averageUnitRevenue` | Average annual revenue per unit |
| `totalUnits` | Current total system size |
| `franchisedUnits` | Franchisee-owned units |
| `companyOwnedUnits` | Corporate-owned units |
| `newUnitsOpened` | Units opened in the latest reported year |
| `unitHistory` | Franchised and company-owned units per `year`, up to five years |
| `franchisingSince` | Year the brand started franchising |
| `dataYear` | Year the unit and revenue figures refer to |
| `categories` | Every BizBuySell category the brand is listed under |
| `availableStates` | State and province codes where the brand grants territories |
| `availableInCanada` | Whether the brand franchises in Canada |
| `classifications` | Tags such as *Training and Support* or *Financing Available* |
| `trainingProvided` | Whether the franchisor provides training |
| `headquarters` | Corporate HQ city and state |
| `ceoName` | Publicly listed CEO |
| `stockTicker` | Ticker symbol, if the parent is public |
| `imageUrl` | Brand logo image URL |
| `extraction_datetime` | UTC timestamp when the item was extracted (ISO-8601) |
| `extraction_date` | Extraction date in `mm-dd-yyyy` format |

⚠️ **Financial fields are self-reported by the franchisor and may be missing.** In a measured sample of 40 brands, brand name, investment range, franchise fee, categories, and territories were present for all of them, while net worth and average unit revenue were present for roughly three quarters. The Actor reports exactly what BizBuySell publishes and **never guesses a value** — a missing figure comes back as `null`.

### How do I scrape franchise opportunities from BizBuySell?

1. Click **Try for free** to open the Actor in **Apify Console**.
2. Under **🔍 Search filters**, pick your **franchise categories** — or leave it empty to scrape all 28.
3. Optionally narrow by **state** (where the brand offers territories) and by **brand name**.
4. Under **💰 Investment range**, set a **minimum** and/or **maximum total investment** in USD. Leave both at `0` for any investment level.
5. Under **⚙️ Limits**, set **Maximum results** (default `50`). Start small to preview the data, then raise it. On the free plan this is capped at 25.
6. Click **Start** and watch the results fill in.
7. Download the dataset as **JSON, CSV, Excel, XML, or HTML**, or pull it straight from the **Apify API**.

### Input

**All seven inputs are optional and none are required.** There is no `startUrls` field and no `proxyConfiguration` field — the Actor posts your search criteria directly to BizBuySell's internal listing API, so there are no URLs to assemble and no proxy to configure.

| Field | Type | Default | Description |
|---|---|---|---|
| `categories` | array (multi-select) | `[]` | Franchise categories to include, from 28 options such as *Restaurant and Food*, *Home Services*, or *Child Related*. Multiple categories are combined with **OR**, so picking several widens the search. |
| `states` | array (multi-select) | `[]` | Two-letter US state codes. Returns brands granting territories in at least one of them — a brand headquartered in Florida still matches Texas if it sells Texas territories. |
| `keyword` | string | `""` | Only brands whose **name** contains this text, e.g. `pizza` matches "Pizza Hut" and "Marco's Pizza". Case-insensitive, matched against the brand name only, not the description. |
| `includeInactive` | boolean | `false` | Turn on to also collect franchises whose advertiser is no longer active. Roughly doubles the results, but those listings often have incomplete financials. |
| `investmentMin` | integer (USD) | `0` | Minimum total investment. `0` = no lower limit. Must not exceed `investmentMax`. |
| `investmentMax` | integer (USD) | `0` | Maximum total investment. `0` = no upper limit. |
| `maxResults` | integer | `50` | Stop after this many franchises. `0` collects everything matching your filters (~900 with the default filters). **Free plan is capped at 25, including when set to `0`.** |

Example input:

```json
{
  "categories": ["Restaurant and Food"],
  "states": ["TX", "FL"],
  "investmentMax": 500000,
  "maxResults": 50
}
```

### Output example

Each franchise becomes one dataset record. You can download the dataset in various formats such as **JSON, HTML, CSV, or Excel**, or fetch it from the API.

```json
{
  "franchiseId": 3417,
  "name": "Take 5 Oil Change",
  "url": "https://www.bizbuysell.com/franchise-for-sale/take-5-oil-change/",
  "urlStub": "take-5-oil-change",
  "website": "https://www.take5franchise.com/what-it-takes/",
  "description": "Simple Model with Superior Unit Level Economics",
  "cashRequired": 2300000,
  "netWorthRequired": 5750000,
  "franchiseFee": 35000,
  "totalInvestmentMin": 2300000,
  "totalInvestmentMax": 3500000,
  "fees": [
    { "type": "franchiseFee", "value": "$45,000", "percent": null, "base": null },
    { "type": "royaltyFee", "value": null, "percent": "5.0%", "base": "Gross Sales" },
    { "type": "advertisingFee", "value": null, "percent": "7.0%", "base": "Gross Sales" }
  ],
  "averageUnitRevenue": 1235518,
  "totalUnits": 1142,
  "franchisedUnits": 500,
  "companyOwnedUnits": 710,
  "newUnitsOpened": 179,
  "unitHistory": [
    { "year": 2023, "franchisedUnits": 325, "companyOwnedUnits": 643 },
    { "year": 2024, "franchisedUnits": 432, "companyOwnedUnits": 710 }
  ],
  "franchisingSince": 2017,
  "dataYear": 2024,
  "categories": ["Automotive", "Business Services", "High Capital Franchises"],
  "availableStates": ["AZ", "FL", "IL", "IN", "IA", "KS", "MI", "MO", "NE", "PA", "TN", "VA"],
  "availableInCanada": false,
  "classifications": ["Training and Support", "Financing Available"],
  "trainingProvided": true,
  "headquarters": "Charlotte, NC",
  "ceoName": "Jonathan Fitzpatrick",
  "stockTicker": null,
  "imageUrl": "https://www.bizbuysell.com/fnw/images/362/362/75692b1b-6cea-4fba-a54e-253b9b2c21c7.gif",
  "extraction_datetime": "2026-08-07T22:44:37.698225+00:00",
  "extraction_date": "08-07-2026"
}
```

### How much does it cost to scrape BizBuySell franchises?

This Actor uses **pay per event (PPE)** pricing. You are billed only for two events — starting the Actor, and each franchise it actually delivers to the dataset. There are **no compute-unit charges**, no proxy surcharge, and **no charge for time spent running**: a run that finds nothing costs only the start event.

| Event | When it is charged | Price |
|---|---|---|
| **Actor start** (`apify-actor-start`) | Once per run | **$0.00005** |
| **Franchise scraped** (`apify-default-dataset-item`) | Once per franchise pushed to the dataset | See the table below |

The price of the *franchise scraped* event depends on your Apify plan:

| Apify plan | Price per 1,000 franchises | Price per event |
|---|---|---|
| 🆓 Free | $3.00 | $0.0030 |
| ⭐ Starter | $2.00 | $0.0020 |
| 🚀 Scale | $1.50 | $0.0015 |
| 🏢 Business | $0.99 | $0.00099 |

#### What a typical run costs

| Run | Results | 🆓 Free | ⭐ Starter | 🚀 Scale | 🏢 Business |
|---|---|---|---|---|---|
| Free-plan run (hard cap) | 25 | **$0.08** | $0.05 | $0.04 | $0.03 |
| Quick preview | 50 | — | $0.10 | $0.08 | $0.05 |
| One category | 100 | — | $0.20 | $0.15 | $0.10 |
| Large filtered slice | 500 | — | $1.00 | $0.75 | $0.50 |
| **Full directory** | ~900 | — | **$1.80** | **$1.35** | **$0.89** |
| Full directory + `includeInactive` | ~1,800 | — | $3.60 | $2.70 | $1.78 |

Every total includes the $0.00005 Actor start event, which is too small to change any figure above.

Every Apify plan includes **monthly platform credits** — the free plan comes with **$5 per month**, which covers the 25-franchise cap many times over. See [Apify pricing](https://apify.com/pricing) for current plan details.

#### How to keep the cost down

- **Filter before you scale.** `categories`, `states`, `keyword`, and the investment range all cut the result count *before* anything is billed, so a targeted run of 100 brands costs a fraction of the full directory.
- **Set `maxResults` on the first run.** Try 10–25 to confirm the fields you need are populated, then raise it — the event only fires for franchises actually delivered.
- **Leave `includeInactive` off.** It roughly doubles both the result count and the bill, with records whose financials are often blank.
- **Schedule monthly, not daily.** Franchise fees, royalties, and unit counts move slowly — a monthly run is enough to track changes via `extraction_date`.
- **Reuse the key-value store when resuming.** The Actor remembers how many results it already pushed, so a restarted run does not re-emit — or re-charge for — franchises you already have.

### Use cases

- 🧾 **Franchise buyers** — build a shortlist you can actually sort. Filter to what your capital supports, then rank by royalty percentage or unit growth instead of clicking through profiles one at a time.
- 🤝 **Franchise brokers and consultants** — keep a current database of brands, investment levels, and available territories to match against client budgets.
- 📈 **Franchisors and their agencies** — benchmark your franchise fee, royalty percentage, investment range, and unit growth against every competitor in your category.
- 💼 **Private equity and M\&A teams** — screen franchise systems by unit count, growth trajectory, and average unit revenue to source acquisition targets.
- 📊 **Market researchers** — schedule recurring runs and use `extraction_date` to track how investment requirements and franchise fees move across categories over time.
- 🎯 **Lead-gen and ad agencies** — segment the franchise market by category, capital tier, and expansion state to target the right brands.

### Tips for better BizBuySell scraping runs

- **Preview before you commit.** Set `maxResults` to 10 on the first run, check the columns, then raise it.
- **Filter by state on the brand's terms.** `states` matches where a franchise is *granting territories*, so a national brand shows up under every state it is expanding into — not just its home state.
- **Leave `includeInactive` off** unless you specifically want lapsed advertisers. It roughly doubles the result count with records whose financials are often blank.
- **Categories are OR, not AND.** Selecting more categories widens the result set rather than narrowing it.
- **Schedule a monthly run** and diff on `extraction_date` to track fee changes and unit growth across a category.
- **Keep memory at 512 MB.** The Actor is pinned to 512 MB and does not benefit from more — it makes API calls, not browser renders.

### Other BizBuySell Actors you might like

| Actor | What it scrapes |
|---|---|
| [BizBuySell Businesses for Sale Scraper](https://apify.com/datacach/bizbuysell-businesses-for-sale-scraper) | Individual businesses and franchise resales listed for sale — a different dataset from the franchisor directory this Actor collects |

### FAQ

#### Is it legal to scrape BizBuySell franchise data?

This Actor collects only **publicly available information** — the same franchise profiles any visitor can view without logging in. It extracts **no personal contact details**: no phone numbers, no email addresses. `ceoName` is a publicly listed corporate officer, not a lead. Scraping public data is generally legal, but you are responsible for how you use the output. If you plan to process it commercially or at scale, get your own legal advice and review BizBuySell's Terms of Service.

#### How many franchises can I scrape from BizBuySell?

Around **900** — the full active directory — on a paid plan with `maxResults` set to `0`. Turning on `includeInactive` roughly doubles that with lapsed advertisers. On the **free plan the run stops at 25** (see [Free vs. paid plans](#free-vs-paid-plans-what-are-the-limits)).

#### Why are some financial fields empty or `null`?

Because the **franchisor did not publish them**. Fees, royalties, net worth, average unit revenue, and unit counts are all self-reported. The Actor reports exactly what BizBuySell shows and never guesses a value.

#### Does this Actor scrape individual businesses for sale?

No. This Actor covers the **franchisor directory** — brands granting new franchises. For businesses and franchise resales listed for sale, use the [BizBuySell Businesses for Sale Scraper](https://apify.com/datacach/bizbuysell-businesses-for-sale-scraper).

#### Can I export BizBuySell franchise data to CSV or Excel?

Yes. Every run's dataset can be downloaded as **JSON, CSV, Excel, XML, or HTML** from the Output tab, or pulled programmatically from the **Apify API**.

#### Can I run this scraper on a schedule or via API?

Yes. Apify gives you **scheduled runs**, **webhooks**, a full **REST API**, and integrations with **Make, Zapier, Google Sheets, and Slack**, plus run monitoring and failure alerts.

#### Do I need to configure a proxy or start URLs?

No. There is **no `startUrls` input and no `proxyConfiguration` input**. The Actor posts your search criteria straight to BizBuySell's internal listing API and handles networking itself.

#### Can I get more data fields or a custom version?

Yes. Open an issue on the **Issues** tab describing what you need. Custom scraping solutions are available on request.

### Support

Found a bug, or a field that stopped populating? Report it on the **Issues** tab of this Actor and it will be looked at. **Feature requests and custom-solution enquiries** are welcome there too.

# Actor input Schema

## `categories` (type: `array`):

Only return franchises listed under these BizBuySell categories, e.g. <code>Restaurant and Food</code> or <code>Home Services</code>. Categories are combined with OR, so picking several widens the search. Leave empty to scrape every category.

## `states` (type: `array`):

Only return franchises that are opening locations in at least one of these US states, e.g. <code>TX</code> or <code>CA</code>. This is where the franchise offers territories, not where its head office is, so a brand headquartered in Florida still matches Texas if it sells Texas territories. Leave empty for nationwide coverage.

## `keyword` (type: `string`):

Only return franchises whose brand name contains this text, e.g. <code>pizza</code> matches "Pizza Hut" and "Marco's Pizza". Case-insensitive, and matched against the brand name only — not the description. Leave empty to keep every brand.

## `includeInactive` (type: `boolean`):

Turn on to also collect franchises whose advertiser is no longer active, which roughly doubles the results but adds listings whose financial fields are often incomplete. Off (the default) returns only the ~900 franchises the site actually shows today.

## `investmentMin` (type: `integer`):

Only return franchises whose total investment is at or above this amount in US dollars, e.g. <code>50000</code>. Must not be greater than the maximum. Leave at 0 for no lower limit.

## `investmentMax` (type: `integer`):

Only return franchises whose total investment is at or below this amount in US dollars, e.g. <code>250000</code>. Leave at 0 for no upper limit.

## `maxResults` (type: `integer`):

Stop after this many franchises. Set to 0 to collect everything that matches your filters (~900 with the default filters). You are charged per result, so start small to preview the data and raise the limit once the output looks right. <b>Free plan is capped at 25 results</b>, including when this is set to 0.

## Actor input object example

```json
{
  "categories": [
    "Restaurant and Food"
  ],
  "states": [],
  "keyword": "",
  "includeInactive": false,
  "investmentMin": 0,
  "investmentMax": 0,
  "maxResults": 50
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# 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 = {
    "categories": [
        "Restaurant and Food"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datacach/bizbuysell-franchises-for-sale-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 = { "categories": ["Restaurant and Food"] }

# Run the Actor and wait for it to finish
run = client.actor("datacach/bizbuysell-franchises-for-sale-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "categories": [
    "Restaurant and Food"
  ]
}' |
apify call datacach/bizbuysell-franchises-for-sale-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datacach/bizbuysell-franchises-for-sale-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/XANHWjoyPajx0BSt8/builds/BQAuUcE4s04wUIYqH/openapi.json
