BusinessesForSale.com Scraper - Businesses, Prices & Financials
Pricing
from $1.50 / 1,000 results
BusinessesForSale.com Scraper - Businesses, Prices & Financials
From $1.5/1K. Extract businesses and franchises listed for sale on BusinessesForSale.com. Search by keywords, country, price, revenue, profit, sort, or use search/listing URLs. Returns title, asking price, revenue, cash flow, location, premises size, employees, photos, categories, and description.
Pricing
from $1.50 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
5
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
BusinessesForSale.com Scraper: Business and Franchise Listings for Sale
BusinessesForSale.com Scraper turns BusinessesForSale.com into structured listing data. Build a search from keywords, market and financial filters, or paste any search-result or individual listing URL, and get the full record: asking price, revenue, cash flow, location, premises size, employees, year established, trading hours, the complete photo gallery and the listing description. Search the worldwide catalogue or pin to a single market, walk as many result pages as you ask for, and export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Two ways to start. Build a search from filters (keywords, country, price/revenue/cash-flow ranges, sort order) or paste any search-result URL, both of which walk as many result pages as you ask for, or paste an individual listing URL for a single record.
- Rich detail on demand. Turn on detail enrichment for the full description, every gallery photo, premises size, employee count, year established, trading hours and lease/freehold tenure, on top of the headline financials.
- Server-side filters that actually narrow the catalogue. Keywords, global coverage or one of seven markets, asking price/revenue/cash-flow ranges, disclosed-only toggles, and eight sort orders.
- Global coverage. Search the worldwide catalogue or pin to a single market: United States, United Kingdom, Australia, Canada, Ireland, New Zealand or South Africa.
- Cost control built in. A results-only search run skips the detail-enrichment surcharge, and Max pages / Max listings cap any run before it grows.
- Built for monitoring. Incremental mode returns only new and changed listings on repeat runs against the same search, and Resume continues one interrupted run without re-scraping what you already collected.
- Optional delivery into your other apps. Pipe results into Notion, Linear, Airtable or Apify through MCP connectors, no code required.
Use Cases
- Business brokers and M&A advisors: build comparable-listing sets by market, price band and cash flow to benchmark a new mandate.
- Buy-side searchers and search funds: monitor a keyword or category for new listings and get notified only when something changes.
- Franchise researchers: pull franchise fee, investment and financial figures across markets to compare opportunities.
- Market analysts: track listing counts and price/revenue bands in a country over time.
- Lead generation teams: build outreach lists of business sellers in a given industry or region from public listing data.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | "us:sample-coffee-shop" |
url | "https://us.businessesforsale.com/us/sample-coffee-shop.aspx" |
title | "Sample Coffee Shop For Sale" |
listingClass | "business" (also "franchise") |
labels | ["New", "High Value"] |
searchCountry | "us" |
locationText | "Sample City, Sample State, US" |
locationDetail | "Sample City ST 00000" (when Fetch listing details is on) |
country / region / locality | "US" / "Sample State" / "Sample City" |
askingPriceDisplay / askingPriceValue / priceCurrency | "$500,000" / 500000 / "USD" |
businessFunction | "Sell" (also "LeaseOut") |
revenueDisplay / revenueValue | "$300,000" / 300000 |
cashFlowDisplay / cashFlowValue | "$120,000" / 120000 |
tenure | "Lease" (also "Freehold", when Fetch listing details is on) |
sizeSqFt | "1,200" (when Fetch listing details is on) |
tradingHours | "7 a.m. to 6 p.m." (when Fetch listing details is on) |
employees | "5" (when Fetch listing details is on) |
yearsEstablished | "2015" (when Fetch listing details is on) |
description | full listing description text (when Fetch listing details is on) |
categories | [{ "name": "Cafes & Coffee Shops", "url": "https://..." }] |
financials | { "Asking Price": "$500,000", "Revenue": "$300,000", "Cash Flow": "$120,000" } |
details | { "Size in square feet": "1,200", "Trading hours": "...", ... } (when Fetch listing details is on) |
thumbnail | "https://www.businessesforsale.com/uploadsstatic/00000000mediumthumbnail.jpg" |
imageCount / images | 4 / ["https://us.businessesforsale.com/uploads/00000000.jpg", ...] |
scrapedAt | "2026-01-01T00:00:00.000Z" |
Each record can also carry a seller object (name and contact fields) when the detail page discloses one. When Incremental mode is on, every record additionally carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt.
How to Use
- Pick a mode: search (build a query from the filters) or url (paste search-result or listing links).
- For search mode, set keywords, the country/market, and any price, revenue or cash-flow filters and a sort order. For url mode, paste one or more links.
- Turn "Fetch listing details" on or off, and set Max pages / Max listings to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Basic search:
{"mode": "search","keywords": "restaurant","country": "us","maxPages": 3,"maxListings": 50}
Search with financial filters:
{"mode": "search","country": "uk","minPrice": 100000,"maxPrice": 1000000,"minProfit": 50000,"profitDisclosedOnly": true,"sortBy": "PriceAsc","maxPages": 5}
Multiple markets in one run, using URL mode:
{"mode": "url","urls": ["https://us.businessesforsale.com/us/search?Keywords=cafe","https://australia.businessesforsale.com/australian/search?Keywords=cafe"],"maxPages": 3,"maxListings": 100}
Fast, results-only run (no detail pages):
{"mode": "search","keywords": "car wash","country": "us","fetchDetails": false,"maxPages": 10}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/businessesforsale-com-scraper").call(run_input={"mode": "search", "keywords": "restaurant", "country": "us"})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["title"], listing["askingPriceDisplay"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/businessesforsale-com-scraper').call({ mode: 'search', keywords: 'restaurant', country: 'us' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset ID and search results already collected there (matched by listingid) are skipped, so you don't pay twice. Pasted individual listing URLs are always re-fetched regardless of Resume. - Incremental mode (
incrementalMode) is for repeated, scheduled runs over the same search. Each listing is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEAREDorEXPIRED.REAPPEAREDonly appears for a listing that was previously markedEXPIREDand is now found again;EXPIREDis only produced after a run that scans every page of the tracked search with no cap hit and no resume in play, and only withemitExpiredon.stateKeynames or shares the stored state. With Incremental mode off, output is exactly as before.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape, the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search builds a query from the filters below; url scrapes the URLs you paste. |
keywords | string | "" (prefill: "restaurant") | Free-text search, used in search mode. Leave blank to list everything. |
country | string | global | Market to search: global, us, uk, australia, canada, ireland, newzealand, southafrica. |
minPrice | integer | none | Minimum asking price, in the market's local currency. |
maxPrice | integer | none | Maximum asking price. |
minRevenue | integer | none | Minimum yearly sales revenue (turnover). |
maxRevenue | integer | none | Maximum yearly sales revenue. |
minProfit | integer | none | Minimum yearly cash flow / net profit. |
maxProfit | integer | none | Maximum yearly cash flow / net profit. |
priceDisclosedOnly | boolean | false | Hide listings whose asking price is "on request". |
revenueDisclosedOnly | boolean | false | Only listings that disclose revenue. |
profitDisclosedOnly | boolean | false | Only listings that disclose cash flow / profit. |
sortBy | string | Default | Default, Newest, PriceAsc, PriceDesc, RevenueAsc, RevenueDesc, ProfitAsc, ProfitDesc. |
urls | array | none (prefill: ["https://www.businessesforsale.com/search?Keywords=restaurant"]) | Search-result or individual listing URLs, used in url mode. Filter fields above are ignored. |
fetchDetails | boolean | true | Include the full per-listing record: description, all photos, size, employees, trading hours, year established, categories and tenure. Turn off for a faster, cheaper results-only run. |
pageSize | string | "50" | Listings fetched per request: "50" or "100". |
maxPages | integer | 0 (unlimited) | Limit on how many result pages each search/URL returns. 0 walks every available page, bounded by Max listings. |
maxListings | integer | 20 | Stop after this many listings total. 0 means unlimited, bounded then only by Max pages. |
resumeFromRunId | string | none | Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. |
incrementalMode | boolean | false | Return only new and changed listings on repeat, scheduled runs over the same search. |
stateKey | string | none | Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. |
emitUnchanged | boolean | false | Also return (and bill) listings that have not changed since the last run, marked UNCHANGED. |
emitExpired | boolean | false | Also return (and bill) listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced after a complete, uncapped, non-resumed scan. |
proxy | object | Apify Proxy, RESIDENTIAL group, country US | Connection settings. A residential connection is required, see Plan Requirement below. |
mcpConnectors | array | none | Optional MCP connectors to export results into (Notion, Linear, Airtable, Apify). Leave empty to skip. |
notionParentPageUrl | string | none | Notion page under which item pages are created. Required for the Notion connector, ignored by the others. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "us:sample-coffee-shop","url": "https://us.businessesforsale.com/us/sample-coffee-shop.aspx","title": "Sample Coffee Shop For Sale","listingClass": "business","labels": ["New", "High Value"],"searchCountry": "us","locationText": "Sample City, Sample State, US","locationDetail": "Sample City ST 00000","country": "US","region": "Sample State","locality": "Sample City","askingPriceDisplay": "$500,000","askingPriceValue": 500000,"priceCurrency": "USD","businessFunction": "Sell","revenueDisplay": "$300,000","revenueValue": 300000,"cashFlowDisplay": "$120,000","cashFlowValue": 120000,"tenure": "Lease","sizeSqFt": "1,200","tradingHours": "7 a.m. to 6 p.m.","employees": "5","yearsEstablished": "2015","description": "Full listing description text appears here when Fetch listing details is on.","categories": [{ "name": "Cafes & Coffee Shops", "url": "https://us.businessesforsale.com/us/search/cafes-coffee-shops" }],"financials": { "Asking Price": "$500,000", "Revenue": "$300,000", "Cash Flow": "$120,000" },"details": { "Location": "Sample City ST 00000", "Size in square feet": "1,200", "Trading hours": "7 a.m. to 6 p.m." },"thumbnail": "https://www.businessesforsale.com/uploadsstatic/00000000mediumthumbnail.jpg","imageCount": 4,"images": ["https://us.businessesforsale.com/uploads/00000000.jpg"],"scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
This site accepts only residential connections. Select Apify Proxy with the RESIDENTIAL group under Connection (the default), or uncheck "Use Apify proxy" and paste your own residential proxy URLs. A datacenter connection is rejected by the site, and a run started with one will likely return zero items. The actor pins the connection to the United States by default and automatically retries with a fresh connection when a request is refused; you can change the starting country in the Proxy field.
FAQ
How much does it cost?
You pay per listing returned, plus an optional detail-enrichment surcharge that applies only to listings returned with their detail page successfully read (turn "Fetch listing details" off to skip it for search results; a pasted individual listing URL always includes the detail surcharge). The Pricing tab shows the current rates. Use Max listings and Max pages to cap the cost of any run.
Is it legal to scrape BusinessesForSale.com?
This actor collects only publicly available listing data. You are responsible for how you use it: follow BusinessesForSale.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts like price and location are generally not protected, but photos and descriptions may be subject to third-party rights.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns NEW and UPDATED listings; UNCHANGED ones are suppressed (and not billed) unless you turn "Emit unchanged" on. EXPIRED and REAPPEARED are rarer: EXPIRED only appears after a run that scans the whole tracked search with no page/listing cap and no Resume in play, and only with "Emit expired" on; REAPPEARED only appears for a listing that was previously marked EXPIRED this way and is later found again.
What's the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues ONE specific interrupted run from a pasted run or dataset ID, so a large walk that stopped partway can pick up where it left off. Incremental mode is for running the SAME search again and again, typically on a schedule, to get only what changed since the last run. They solve different problems and are not meant to be combined: starting Incremental mode with resumeFromRunId set while that state key already has saved state fails the run with a clear message instead of mixing the two.
Why did my run fail instead of returning an empty dataset?
The run fails with a clear message only when there's no usable connection to start with, when every pasted individual listing URL comes back unreadable, when a pasted resumeFromRunId can't be read, or when Incremental mode is combined with Resume on a search that already has saved state. A search that gets blocked partway through ends normally instead, with zero or partial listings and warnings in the run log, so check the log and re-run for a fresh connection if that happens.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more leads data?
Pair this actor with these related scrapers from the same team:
| 📇 BizBuySell Scraper From $1.5/1K. Extract business-for-sale and franchise listings from bizbuysell.com with... | 📇 BizQuest Scraper From $1/1K. Extract business-for-sale, franchise, and asset listings from BizQuest... |
| 🛒 Flippa Scraper From $0.80/1K. Scrape Flippa listings with full enrichment, including revenue, profit... | 🏠 Crexi Scraper Scrape crexi.com commercial listings: asking price, cap rate, square footage, units, year... |
| 📇 Houzz Pro Scraper From $1/1K. Pull Houzz pro listings across global sites. Search by category and location... | 🏠 ImmobilienScout24.de Scraper $0.9💰/1K for Gold discount. Extract property listings from immobilienscout24.de... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.