# Businesses For Sale Scraper - DealStream Listings & Deals (`parseforge/dealstream-listings-scraper`) Actor

Reads businesses, franchises and M\&A deals listed for sale on DealStream: asking price, cash flow, revenue, industry, county level location and the full deal terms, from a marketplace of 16,900 live listings.

- **URL**: https://apify.com/parseforge/dealstream-listings-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** E-commerce, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.45 / 1,000 business listings

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/actors/running/actors-in-store.md#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

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)](https://apify.com/parseforge?fpr=vmoqkp)

### Businesses For Sale Scraper - DealStream Listings & Deals

**Scrape businesses, franchises and M\&A deals for sale on DealStream, a marketplace of 16,900 live listings.** Every row carries 25 fields: asking price, cash flow, industry, county level location, region, country, and the six flags DealStream publishes, including seller financing and whether real estate is included. No login, no API key. Export to CSV, JSON, Excel or XML.

DealStream has no public API and sits behind DataDome, so a plain HTTP request gets a 403 no matter what headers it sends. This reads the marketplace in a real browser, takes the structured data DealStream itself publishes on every page, and hands back one flat row per listing.

| Who uses it | What they scrape DealStream for |
|---|---|
| Search funds and acquirers | New deals in a size band and an industry, before the broker calls back |
| Business brokers | What comparable businesses are asking and what they earn |
| Private equity and family offices | Deal flow by region, sector and cash flow, on a schedule |
| Lenders and SBA underwriters | Asking price against cash flow across a sector, for a sanity band |
| Market analysts | Multiples and supply by industry, county and state |

### What it does

This Actor reads DealStream's browse pages in a real browser and returns each listing as a flat row. Every listing carries:

- 💼 **The business:** title, industry, summary, county level location, region, country and the listing URL.
- 💰 **The money:** asking price and cash flow as numbers, currency, and whether the listing is still available.
- 🚩 **The six DealStream flags:** real estate included, seller financing, management will stay, relocatable, new arrival and franchise, each as its own Yes or No column.
- 📄 **Optional blocks:** the full seller write up, revenue, the nine deal terms, the posted and renewed dates, the category path and DealStream's raw structured record.
- 🗂️ **A second output:** the directory of every browse page DealStream publishes, which is how you learn the valid values for the browse field.

Results export to CSV, JSON, Excel or XML, or stream from the API.

### What you can do with DealStream data

**🎯 Build a deal pipeline in one industry.**

Point it at a category browse page, set a cash flow floor, and get every listing in that sector with its asking price and multiple.

**📊 Price a business against its comparables.**

Pull a category and a region, take asking price and cash flow on every row, and read the band the market is actually asking.

**📍 Cover a territory.**

Walk the state and county browse pages and get every business for sale inside a footprint, refreshed on a schedule.

**🔎 Watch for new arrivals.**

Turn on the listing dates and keep the rows whose posted date is recent, which is the difference between a fresh deal and one that has been sitting for a year.

### Why choose this scraper

| | What you get |
|---|---|
| **It gets in at all** | DealStream runs DataDome. Every page here is a real browser navigation on a residential address, with a fresh browser opened before the site cuts the session off. |
| **The numbers are the source's own** | Asking price, currency, region and country come from the schema.org record DealStream publishes, not from parsing a dollar sign out of a div. |
| **Revenue, which the browse page never shows** | Turn on the financials block and each listing carries its published revenue alongside asking price and cash flow. |
| **The nine deal terms** | Represented by a broker, buyer fee, willing to co-broke, principals only, franchise, seller financing, management will stay, relocatable and real estate. |
| **Filters that cost you nothing** | Price band, cash flow floor, region, country, keywords and the six flags. A listing a filter drops is never written and never billed. |
| **Browse pages only** | DealStream's robots file reserves its /search endpoint. This reads the browse pages and the listing pages it allows, and nothing else. |

### How it compares

There is no other DealStream scraper on Apify. The neighbouring actors cover BizBuySell, BizQuest, BusinessesForSale and Empire Flippers, which are ordinary HTTP sites; DealStream is not, and that is most of the difference in what this costs and what it takes to run.

| Feature | ParseForge DealStream | scrapesage/bizbuysell | solidcode/bizquest | haketa/businessesforsale |
|---|---|---|---|---|
| Covers DealStream | Yes | No | No | No |
| Asking price and cash flow on the base row | Yes | Yes | Yes | Yes |
| Revenue | Optional block | Optional block | Optional block | No |
| Nine deal terms | Yes | No | No | No |
| Browse category directory | Yes | No | No | No |
| Price per row | $0.005 | $0.004 | $0.00114 | $0.0015 |

### What a DealStream listing looks like

```json
{
 "rowType": "listing",
 "listingId": "nlyydy",
 "postId": "69b2d78630d8c019d25a4a5a",
 "title": "Established German Auto Repair Shop",
 "listingUrl": "https://dealstream.com/d/biz-sale/auto-repair/nlyydy",
 "summary": "This well-established independent European automotive repair and service facility specializes in German and European-engineered vehicles, including BMW, Mercedes-Benz, Audi, Volkswagen, Porsche, Rolls Royce, Bentley, Ferrari, Lamborghini, Jaguar, Land Rover, Aston Martin, McLaren, Alfa Romeo, Maserati,...",
 "industry": "Auto Repair Shops, Garages",
 "location": "Broward County, FL",
 "state": "Florida",
 "country": "US",
 "askingPriceUsd": 125000,
 "cashFlowUsd": 90751,
 "currency": "USD",
 "availability": "InStock",
 "realEstateIncluded": "No",
 "sellerFinancing": "No",
 "managementWillStay": "Yes",
 "relocatable": "No",
 "newArrival": "No",
 "franchise": "No",
 "flags": [
  "Management Will Stay"
 ],
 "ratingValue": 5,
 "reviewCount": 1,
 "iconUrl": "https://dealstream.com/assets/images/listingicons/png/fak fa-ds-autorepair.png",
 "scrapedAt": "2026-09-01T16:50:12.965Z"
}
```

Add `"outputs": ["listings", "categories"]` and you also get one row per browse page:

```json
{
 "rowType": "category",
 "title": "Businesses",
 "browsePath": "businesses-for-sale",
 "browseUrl": "https://dealstream.com/businesses-for-sale",
 "lastModified": "2026-09-01",
 "sourceSitemap": "https://dealstream.com/sitemap-us-businessforsale-0001.xml",
 "scrapedAt": "2026-09-01T16:54:44.081Z"
}
```

### Configure the run

The browse page you pick is the server side filter, because DealStream's own search form is off limits under its robots file. Leave `browsePaths` at `businesses-for-sale` for the whole marketplace, or name a category or a place. Everything under Filters runs on the rows that came back, and a dropped row is not billed.

Every laundromat and car wash on the marketplace, with the numbers:

```json
{ "browsePaths": ["laundromats-for-sale", "car-washes-for-sale"], "maxItems": 300 }
```

Florida businesses earning over $200,000, with revenue and the deal terms:

```json
{ "browsePaths": ["florida-businesses-for-sale"], "minCashFlowUsd": 200000, "includeFinancials": true, "includeDealTerms": true, "maxItems": 100 }
```

Anything under a million with seller financing on the table:

```json
{ "maxAskingPriceUsd": 1000000, "requireSellerFinancing": true, "maxPagesPerBrowsePath": 20, "maxItems": 250 }
```

### Pricing

Pay-per-event: **$0.005 per listing**, dropping to $0.00445 at higher volume, plus $0.002 per browse page of 25, **$0.08 per browser session**, and a $0.008 run-start fee. That last figure is $0.002 a gigabyte and the actor runs in a 4 GB container, because that is what a real browser needs. That last one is the honest cost of a DataDome site, and it is measured rather than guessed: a browser launch costs $0.045 to run, DealStream cuts each one off after about 11 pages and remembers the address, so a long run opens a fresh browser roughly every 250 listings.

| Listings collected | Base row | Every block on |
|---|---|---|
| 100 | $0.60 | $2.25 |
| 1,000 | $5.41 | $22.39 |
| 10,000 | $54.01 | $223.81 |

Each optional block is billed separately and only when it actually returned something: opening the listing page $0.004, full description $0.001, revenue and financials $0.0015, deal terms $0.0012, listing dates $0.0006, category path $0.0006, raw record $0.0004. Browse category rows are $0.001 each and a sitemap read is $0.002.

The right hand column is higher than you might expect, and the reason is worth knowing before you tick the boxes: a browse page returns 25 listings in one browser navigation, and a listing page returns one. Turning on any block that needs the listing page makes the run about 25 times more browser work per row. Leave them off unless you need revenue, the deal terms or the dates. New Apify accounts start with $5 in free credit.

### Free users

Free-plan runs return up to 10 rows as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to collect up to 1,000,000 rows per run.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [Businesses For Sale Scraper](https://apify.com/parseforge/dealstream-listings-scraper?fpr=vmoqkp).
3. Pick a browse page, set any filters and `maxItems`, and click **Start**.
4. Export the results as CSV, Excel, JSON or XML from the **Dataset** tab.

Run it programmatically through the [Apify API](https://docs.apify.com/api/v2) or the [ApifyClient](https://docs.apify.com/api/client/js) for JavaScript and Python.

### Use with AI agents (MCP)

Give an AI agent live access to DealStream through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/dealstream-listings-scraper"
```

Then prompt it in plain language:

- *"Find businesses for sale in Florida with cash flow over $300,000 and tell me the asking price multiple on each."*
- *"List every laundromat for sale under $500,000 that includes real estate."*
- *"Which industries on DealStream have the most listings with seller financing?"*

Copy this into ChatGPT, Claude, or Cursor to start:

```
Use the Apify Actor "parseforge/dealstream-listings-scraper" to collect businesses for sale from DealStream. Input: { "browsePaths": ["<slug>-for-sale"], "minCashFlowUsd": <n>, "maxAskingPriceUsd": <n>, "maxItems": <n> }. It returns title, industry, location, state, country, askingPriceUsd, cashFlowUsd, the six flags and listingUrl per listing. Call it with the ApifyClient and my APIFY_TOKEN.
```

### Troubleshooting

**Why am I getting no results?**

A browse slug has to exist. `florida-businesses-for-sale` works, `florida` does not. Run once with `"outputs": ["categories"]` to get the directory of every browse page DealStream publishes, then copy the slug in.

**Why fewer listings than I asked for?**

Two reasons. Your filters removed rows, and the log prints how many: `1,204 listing(s) dropped by the filters, none billed`. Or the browse page ran out: `maxPagesPerBrowsePath` caps how deep the walk goes, and 25 listings a page means 20 pages is 500 listings.

**Why is a field empty?**

DealStream does not fill every field on every listing. Measured over one page of 25: industry and location on 25, asking price on 22, cash flow on 23, region and country on 22. An empty field is the listing's real state, written as `Not Disclosed`. Revenue is empty on the base row by design: it exists only on the listing page, so it needs the financials block.

**Why is the run slow, and why does it open several browsers?**

DealStream runs DataDome, so every page is a real browser navigation, and a session is cut off after about 11 pages. The actor opens a fresh browser on a fresh address before that happens. That is the run working correctly, not failing.

**A field stopped filling.**

DealStream changed its page. Email us with your run ID so we can update the parser.

### FAQ

| Question | Answer |
|---|---|
| Do I need a DealStream account? | No. It reads the public browse and listing pages. |
| Why is this more expensive than a BizBuySell scraper? | Those sites answer a plain HTTP request. DealStream answers 403 and needs a real browser on a residential address, and the browser is billed separately so you can see exactly what that costs. |
| Does it use DealStream's search filters? | No. The site's robots file reserves its /search endpoint, so the browse page is the server side filter and the rest of the filtering runs on the rows that came back. Dropped rows are not billed. |
| How do I find valid browse slugs? | Set `"outputs": ["categories"]` once. It returns every browse page DealStream publishes in its own sitemap. |
| Does it return revenue? | Yes, with the financials block. Revenue is published only on the listing page, so it costs one page load per listing. |
| Can I get the broker's contact details? | No. DealStream keeps enquiries behind its own form and this actor does not touch it. |
| How current are the listings? | The rows are read live at run time. Turn on the listing dates block to see when each was posted and last renewed. |
| How many listings per run? | Free plan: 10. Paid: up to 1,000,000, bounded by the roughly 16,900 listings on the marketplace. |
| Is this an official DealStream product? | No. It is unofficial and reads only public DealStream data. |

### Related actors

- [BizBuySell Scraper](https://apify.com/parseforge/bizbuysell-scraper-v2?fpr=vmoqkp): businesses for sale from the largest US marketplace.
- [Flippa Scraper](https://apify.com/parseforge/flippa-scraper?fpr=vmoqkp): online businesses, apps and domains for sale.
- [Business Bankruptcy Filings Scraper](https://apify.com/parseforge/business-bankruptcy-filings-scraper?fpr=vmoqkp): distressed companies from the federal filings.
- [FINRA BrokerCheck Scraper](https://apify.com/parseforge/finra-brokercheck-scraper?fpr=vmoqkp): background on brokers and their firms.
- [BigIron Auction Scraper](https://apify.com/parseforge/bigiron-auctions-scraper?fpr=vmoqkp): farm and construction equipment sold at auction.

Browse the full [ParseForge collection](https://apify.com/parseforge?fpr=vmoqkp) for more scrapers.

🆘 **Need help?** Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ **Disclaimer.** This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by DealStream. It collects only publicly available listing data from the browse and listing pages, and it does not read the search, profile, messaging or enquiry areas that DealStream's robots file reserves. Listing content is written by sellers and brokers and is not verified by DealStream or by us. You are responsible for using the data in compliance with DealStream's terms and applicable laws, including GDPR, CCPA and PIPL. Do not use it to identify, profile, or target individuals.

# Actor input Schema

## `browsePaths` (type: `array`):

DealStream browse slugs to walk, for example 'tobacco-shops-for-sale', 'florida-businesses-for-sale' or 'broward-county-businesses-for-sale'. Leave empty to walk 'businesses-for-sale', which is the whole marketplace. Turn on the category directory output once to get the full list of valid slugs.

## `maxItems` (type: `integer`):

Free users: limited to 10 items (preview). Paid users: up to 1,000,000.

## `maxPagesPerBrowsePath` (type: `integer`):

How deep to page into each browse slug. Each page holds 25 listings. DealStream's bot defence lets a browser session read about 11 pages before it cuts in, so the actor opens a fresh browser when that happens; a lower number here means fewer browser restarts and a cheaper run.

## `outputs` (type: `array`):

What the run collects. Listings is the marketplace inventory. Category directory is one row per browse page DealStream publishes, with its slug, which is how you learn the valid values for the field above. Pick both and maxItems is split evenly, with whatever one does not use rolling into the other.

## `startUrls` (type: `array`):

Optional. Paste DealStream listing URLs (https://dealstream.com/d/...) to read those exact listings instead of walking a browse page. Ignored when empty.

## `keywords` (type: `array`):

Keep only listings whose title, industry or summary contains one of these words. DealStream's own search box is off limits under its robots file, so this filter runs on the rows the browse page returned. A listing dropped here is never billed.

## `minAskingPriceUsd` (type: `integer`):

Drop listings priced below this. Listings with no published price are dropped by any price filter; leave both empty to keep them.

## `maxAskingPriceUsd` (type: `integer`):

Drop listings priced above this.

## `minCashFlowUsd` (type: `integer`):

Drop listings whose published cash flow is below this. Listings with no published cash flow are dropped when this is set.

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

Keep only listings in these regions, as DealStream spells them: 'Florida', 'Texas', 'Ontario'. Matched case insensitively against the region in the listing's structured data.

## `countries` (type: `array`):

Two letter country codes as DealStream publishes them, for example 'US', 'CA', 'GB'.

## `requireRealEstate` (type: `boolean`):

Keep only listings flagged 'Real Estate Included'.

## `requireSellerFinancing` (type: `boolean`):

Keep only listings flagged 'Seller Financing'.

## `requireManagementStays` (type: `boolean`):

Keep only listings flagged 'Management Will Stay'.

## `requireRelocatable` (type: `boolean`):

Keep only listings flagged 'Relocatable'.

## `includeFullDescription` (type: `boolean`):

Opens each listing's own page and adds the complete seller write up. The browse page carries only a truncated summary. One extra page load per listing.

## `includeFinancials` (type: `boolean`):

Adds the listing's published revenue, plus asking price and cash flow as the financials table states them. Revenue appears only on the listing page, never on the browse page.

## `includeDealTerms` (type: `boolean`):

Adds the ten deal conditions DealStream publishes: represented by a broker, buyer fee, seller financing, willing to co-broke, principals only, franchise, management will stay, relocatable and real estate.

## `includeDates` (type: `boolean`):

Adds the date the listing was first posted and the date it was last renewed, which is how you tell a fresh deal from one that has been sitting.

## `includeCategoryPath` (type: `boolean`):

Adds the breadcrumb category hierarchy from the listing page and the browse URL of each level.

## `includeRawJsonLd` (type: `boolean`):

Adds DealStream's own schema.org Product record for the listing, untouched. Useful when you want a field this actor does not map.

## `proxyMode` (type: `string`):

DealStream remembers the IP that its bot defence blocked, so a shared datacenter address stops working after a few hundred listings. Residential is the default for that reason. 'None' is cheaper and works from a clean address, so it is worth trying for small runs.

## `countryCode` (type: `string`):

Two letter country for the residential proxy. DealStream is a US marketplace, so US is the default.

## Actor input object example

```json
{
  "browsePaths": [
    "businesses-for-sale"
  ],
  "maxItems": 10,
  "maxPagesPerBrowsePath": 10,
  "outputs": [
    "listings"
  ],
  "requireRealEstate": false,
  "requireSellerFinancing": false,
  "requireManagementStays": false,
  "requireRelocatable": false,
  "includeFullDescription": false,
  "includeFinancials": false,
  "includeDealTerms": false,
  "includeDates": false,
  "includeCategoryPath": false,
  "includeRawJsonLd": false,
  "proxyMode": "residential",
  "countryCode": "US"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `csv` (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 = {
    "browsePaths": [
        "businesses-for-sale"
    ],
    "maxItems": 10,
    "maxPagesPerBrowsePath": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/dealstream-listings-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 = {
    "browsePaths": ["businesses-for-sale"],
    "maxItems": 10,
    "maxPagesPerBrowsePath": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/dealstream-listings-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 '{
  "browsePaths": [
    "businesses-for-sale"
  ],
  "maxItems": 10,
  "maxPagesPerBrowsePath": 10
}' |
apify call parseforge/dealstream-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parseforge/dealstream-listings-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/APYJpiIdaGKne14yC/builds/NptwybOfFUQsZ1FTf/openapi.json
