# Transworld Scraper – US Businesses for Sale (`outlandish_mainsail/transworld-business-scraper`) Actor

Scrape businesses for sale from Transworld Business Advisors (tworld.com), a large US business-broker network: asking price, cash flow (SDE), sales, EBITDA, down payment, employees, location, industry and the listing broker's business contact.

- **URL**: https://apify.com/outlandish_mainsail/transworld-business-scraper.md
- **Developed by:** [Andreas v](https://apify.com/outlandish_mainsail) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Transworld Scraper – US businesses for sale (tworld.com)

Scrape **businesses for sale from [Transworld Business Advisors](https://www.tworld.com/buy-a-business/business-listing-search)** (tworld.com), one of the largest business-brokerage franchise networks in the US, with ~3,500 active listings. Get one clean record per listing: **asking price, cash flow (SDE), sales, EBITDA, down payment, inventory, FF\&E, rent, employees, year established, reason for selling, industry, location** and the **listing broker's business contact** (name, email, phone, office). Export as JSON, CSV, Excel or via API.

- ✅ All Transworld listings straight from the broker network, **newest first**
- ✅ **Numbers as numbers** plus a computed **price / SDE multiple**
- ✅ **Filters**: state/location, industry, title keywords, asking price and cash-flow ranges
- ✅ **Broker contacts** for every listing, useful for deal sourcing and broker outreach
- ✅ **Only new listings** mode for daily deal alerts (use with an Apify Schedule)
- ✅ Fast mode (search results only) or full detail mode
- ✅ Polite: plain HTTP, no browser, no proxy, follows the site's `robots.txt` including its 10-second crawl delay

### What data can you get?

| Field | Example | Notes |
|---|---|---|
| `listingId`, `listingNumber`, `url` | `"92460"`, `"2301-889079"` | |
| `title`, `description` | | Full description in detail mode |
| `categories` | `["Construction"]` | Industry |
| `location`, `state`, `area` | `"Orlando, Orange County, Florida"` → `Florida` / `Orlando, Orange County` | |
| `askingPrice`, `downPayment` | `59999`, `50000` | USD |
| `sellerDiscretionaryEarnings` | `43458` | Cash flow (SDE), USD |
| `sales` | `422769` | Yearly sales, USD (detail mode) |
| `ebitda` | | When the broker provides it |
| `priceToSdeMultiple` | `1.38` | askingPrice ÷ SDE, computed |
| `inventory`, `ffe`, `monthlyRent` | `6000` | FF\&E = furniture, fixtures & equipment |
| `employees`, `yearEstablished`, `reasonForSale` | `4`, `1991`, `"RETIRING"` | |
| `ndaRequired` | `true` | Whether the broker requires an NDA for more info |
| `brokerName`, `brokerEmail`, `brokerPhone`, `brokerOffice`, `brokerProfileUrl`, `brokerLicense` | `"Adam Lawson"`, `"alawson@tworld.com"` | Business contact of the listing broker as published by Transworld |
| `image`, `officeSlug`, `currency`, `detailsScraped`, `scrapedAt` | | |

Fast mode (`includeDetails: false`) returns title, industry, location, asking price, down payment, cash flow and image.

### How to use it

1. Click **Start** / **Try for free**.
2. Set **Max listings** and optional filters (state, industry, price, cash flow).
3. Download the dataset (Overview or Financials view) as JSON/CSV/Excel or via API.

#### Input examples

Profitable businesses in Florida and Texas with at least $250k cash flow:

```json
{ "maxItems": 100, "states": ["Florida", "Texas"], "minCashFlow": 250000 }
```

Daily alert of new listings under $1M (use with a Schedule):

```json
{ "maxItems": 50, "maxPrice": 1000000, "skipPreviouslyScraped": true }
```

### Output example

```json
{
  "listingNumber": "2301-889079",
  "url": "https://www.tworld.com/buy-a-business/listings/35-PLUS-YEARS-ESTABLISHED-FAMILY-OWNED-RESIDENTIAL-PAINTING-BIZ",
  "title": "35 PLUS YEARS ESTABLISHED FAMILY-OWNED RESIDENTIAL PAINTING BIZ",
  "categories": ["Construction"],
  "location": "Orlando, Orange County, Florida",
  "state": "Florida",
  "askingPrice": 59999,
  "downPayment": 50000,
  "sales": 422769,
  "sellerDiscretionaryEarnings": 43458,
  "priceToSdeMultiple": 1.38,
  "ffe": 6000,
  "employees": 4,
  "yearEstablished": 1991,
  "reasonForSale": "RETIRING",
  "brokerName": "Adam Lawson",
  "brokerEmail": "alawson@tworld.com",
  "brokerPhone": "(407) 745-0468",
  "brokerOffice": "Orlando",
  "detailsScraped": true
}
```

### Speed and cost

Transworld's `robots.txt` asks crawlers to wait 10 seconds between requests, and this Actor respects that. So:

- **Detail mode**: about 6 listings per minute (100 listings ≈ 17 minutes).
- **Fast mode**: 9 listings per search page, about 50 listings per minute.
- Narrow filters scan more search pages to find matches; `maxSearchPages` (default 100) caps that.

You pay per listing saved. Set a **maximum cost per run** in the run options and the Actor stops when it's reached.

### Use cases

- **Search funds, acquisition entrepreneurs, private equity**: daily deal flow with SDE multiples
- **SBA lenders and business-acquisition lenders**: find deals that need financing, contact the broker
- **Business brokers and M\&A advisors**: competitive intelligence, pricing benchmarks by industry and state
- **Market research**: asking-price multiples by industry and region

### Is it legal? (GDPR / privacy)

The Actor reads only public listing pages that anyone can open without an account, follows `robots.txt` (including the crawl delay) and never logs in. Listings are anonymous: the Actor does **not** collect the seller's identity or any non-public data. It does collect the **listing broker's business contact details** (name, work email, work phone, office) exactly as Transworld publishes them for buyer enquiries. If you process them in the EU/UK, you need a lawful basis under the GDPR (e.g. legitimate interest for B2B outreach), and must honour opt-outs. Don't republish the listings as your own marketplace. You are responsible for how you use the data.

### FAQ

**Why is it slower than other scrapers?** It deliberately follows the site's 10-second crawl delay so it stays welcome. Use fast mode or filters if you need speed.

**Some fields are empty?** Brokers don't fill in every field (e.g. EBITDA, rent). Zero values on the site are returned as `null`.

**Found a problem?** Open an issue on the Issues tab with your run link.

# Actor input Schema

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

Maximum number of listings to save (after filters). Newest listings first. Set 0 for no limit (~3,500 listings; slow, see README).

## `includeDetails` (type: `boolean`):

Open each listing page to add sales, EBITDA, inventory, FF\&E, rent, employees, year established, reason for selling, full description and the listing broker's name, email and phone. Off = fast mode with search-result data only (title, industry, location, asking price, down payment, cash flow).

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

tworld.com listing URLs, e.g. https://www.tworld.com/buy-a-business/listings/... Leave empty to browse all listings with the filters below.

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

Keep listings whose location contains any of these, e.g. 'Florida', 'Texas', 'Orange County'. Case-insensitive.

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

Keep listings whose industry contains any of these, e.g. 'Restaurant', 'Construction', 'Child Care', 'Franchise'.

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

Keep listings whose title contains any of these words, e.g. 'HVAC', 'SBA', 'absentee'.

## `minPrice` (type: `integer`):

Minimum asking price.

## `maxPrice` (type: `integer`):

Maximum asking price.

## `minCashFlow` (type: `integer`):

Minimum seller's discretionary earnings. Listings without SDE are excluded when set.

## `maxCashFlow` (type: `integer`):

Maximum seller's discretionary earnings.

## `includeListingsWithoutPrice` (type: `boolean`):

Only matters when a price filter is set.

## `maxSearchPages` (type: `integer`):

Safety cap on how many search pages (9 listings each) are scanned when filters are narrow. 0 = no cap (all ~390 pages, about 65 minutes because of the site's crawl delay).

## `skipPreviouslyScraped` (type: `boolean`):

Remember listings across runs (named key-value store 'transworld-business-scraper-seen') and skip those saved before. Ideal with a daily Schedule.

## `seenListingsKey` (type: `string`):

Use a different key per saved task if you monitor several searches.

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

Not needed normally.

## Actor input object example

```json
{
  "maxItems": 20,
  "includeDetails": true,
  "includeListingsWithoutPrice": true,
  "maxSearchPages": 100,
  "skipPreviouslyScraped": false,
  "seenListingsKey": "SEEN_IDS",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

All scraped business-for-sale listings in the default dataset.

# 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 = {
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("outlandish_mainsail/transworld-business-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 = { "maxItems": 20 }

# Run the Actor and wait for it to finish
run = client.actor("outlandish_mainsail/transworld-business-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 '{
  "maxItems": 20
}' |
apify call outlandish_mainsail/transworld-business-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,outlandish_mainsail/transworld-business-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/jNjLRHV1RXeUNm4rm/builds/iyNrHEcedin6cBC6n/openapi.json
