# BizQuest Scraper (`piotrv1001/bizquest-scraper`) Actor

Find businesses and asset sales on BizQuest with asking prices, locations, summaries and publicly visible financials. Track newly observed listings and asking-price changes across runs, with optional seller contacts and clear coverage reports for acquisition research.

- **URL**: https://apify.com/piotrv1001/bizquest-scraper.md
- **Developed by:** [FalconScrape](https://apify.com/piotrv1001) (community)
- **Categories:** Lead generation, Business, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listings

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

## BizQuest Scraper — Businesses for Sale & Asking-Price Monitoring

Find acquisition opportunities on BizQuest and track changes to their asking prices. Export businesses and asset sales with titles, locations, asking prices, summaries, images and financial figures where publicly visible.

### ✨ Features

- Business and asset-sale listings from BizQuest search pages.
- Geography, category and other filters carried in your search URLs.
- One global result limit across multiple searches.
- Named monitoring for newly observed listings and asking-price changes.
- Previous asking price and observation timestamps on change records.
- Clear financial-availability fields instead of guessed cash-flow values.
- Optional published seller names, phone numbers and company names.
- Coverage reports for scan limits, repeated pages and unavailable searches.

### 🚀 How it works

1. Open a BizQuest search and apply your desired location, category or price filters.
2. Paste the search URL into **BizQuest search URLs**.
3. Set **Maximum results** (default 50), then choose export or monitoring mode.
4. Run the Actor. Download results as JSON, CSV or Excel and check **Coverage summary**.

#### Default export

```json
{
  "startUrls": [{ "url": "https://www.bizquest.com/businesses-for-sale/" }],
  "maxItems": 50
}
```

#### Monitor the first page of California businesses

```json
{
  "startUrls": [{ "url": "https://www.bizquest.com/businesses-for-sale-in-california-ca/" }],
  "mode": "monitor",
  "stateKey": "california-price-watch",
  "maxPagesPerSearch": 1,
  "maxItems": 100
}
```

The first monitoring run returns a baseline of listings. Reuse the same tracker name and search URLs on later runs to receive newly observed IDs and asking-price changes. A fully scanned, unchanged window returns no rows.

If the result cap prevents the first run from delivering every listing in the window, later runs can return additional existing listings as `newListing`. This means **new to your tracker**, not necessarily newly advertised. Increasing the page limit extends the monitored window without resetting already observed IDs. Changing a search URL creates a separate scope; a new tracker name starts fresh.

#### Florida restaurants with published seller contacts

```json
{
  "startUrls": [{ "url": "https://www.bizquest.com/restaurants-for-sale-in-florida/" }],
  "maxItems": 100,
  "maxPagesPerSearch": 2,
  "includeSellerContacts": true
}
```

### 📥 Input

| Field | Default | Meaning |
|---|---|---|
| `startUrls` | National business search | Up to 20 BizQuest search URLs. Paste filtered URLs directly. |
| `maxItems` | `50` | Maximum returned listing/change rows for the entire run; up to 10,000. |
| `mode` | `snapshot` | `snapshot` for exports, `monitor` for new listings and changes. |
| `stateKey` | `default` | Named tracker for monitoring. |
| `maxPagesPerSearch` | `5` | Maximum pages checked per search; up to 200. Limits no-change checks too. |
| `includeSellerContacts` | `false` | Include published seller/broker names, phones and companies where available. |

Search URLs starting on a later page begin at that page. The Actor preserves query parameters when continuing pagination. If the source resets to a different page, collection stops with a coverage warning.

Individual listing detail URLs, broker profiles, email enrichment and full business-detail extraction are outside this version's scope. Use the search page containing the business. Franchise promotions and advertising entries are excluded from acquisition results.

### 📊 Output

Illustrative example:

```json
{
  "listingId": "1234567",
  "url": "https://www.bizquest.com/business-for-sale/example-business/BW1234567/",
  "title": "Example Service Business",
  "listingType": "business",
  "askingPrice": 450000,
  "currency": "USD",
  "location": "Example County, CA",
  "region": "CA",
  "summary": "Established service business with recurring customers.",
  "cashFlow": null,
  "cashFlowStatus": "signInRequired",
  "ebitda": null,
  "ebitdaStatus": "unavailable",
  "priceReduced": true,
  "recentlyAdded": false,
  "recentlyUpdated": true,
  "realEstateIncluded": false,
  "images": [],
  "eventType": "priceChanged",
  "previousAskingPrice": 500000,
  "firstSeenAt": "2026-09-18T10:00:00.000Z",
  "lastSeenAt": "2026-09-19T10:00:00.000Z",
  "observedAt": "2026-09-19T10:00:00.000Z",
  "searchUrl": "https://www.bizquest.com/businesses-for-sale-in-california-ca/"
}
```

`listingType` is `business` or `assetSale`. Seller contact fields are omitted unless requested. They may identify a seller rather than a licensed broker, and their accuracy is not independently verified.

| Event type | Meaning |
|---|---|
| `snapshot` | Current listing in export mode. |
| `newListing` | First delivery of this listing in this tracker/search scope. |
| `priceChanged` | Two observed numeric asking prices differ. |
| `priceAvailabilityChanged` | An asking price became disclosed or undisclosed; this is not a reduction to zero. |

`firstSeenAt` and `lastSeenAt` are observation times, not listing publication dates. In export mode, firstSeenAt refers to that run. A source `priceReduced` flag is separate from a change measured by your tracker.

Cash flow and EBITDA remain separate, nullable values. `public` means a visible amount was found. `signInRequired` indicates an explicit cash-flow gate. `notPublished` means no amount was displayed; `unavailable` means visibility could not be established. Missing financials never become zero. Changes to financial disclosure alone do not produce monitoring events.

### 💰 Proposed pricing

Configure these events in Apify Console before publication. The Console price at purchase is authoritative.

| Event | Price | When charged |
|---|---:|---|
| Actor start | $0.01 per run | A valid export or monitoring check starts. |
| Listing or change | $0.001 per row | One listing or change record is returned. |

This equals **$1 per 1,000 results plus startup**. Proposed totals are $0.06 for 50 results, $1.01 for 1,000, or $0.01 for a no-change check, with platform usage included when configured accordingly. Unsupported/blocked searches can still incur the startup fee after input validation. Duplicate and unchanged monitored listings have no per-result charge; coverage summaries have no separate charge.

**Listing or change is the primary event.** There is no additional detail event. The run's maximum spending limit can stop collection before the result cap.

### Coverage and monitoring limits

- Monitoring covers only the search pages actually scanned. Ranking changes can bring an existing business into that window as new to the tracker.
- Missing listings are not labelled sold or closed. No sale-status events are generated.
- Asking prices and financial disclosures can change independently. Visible financial completeness varies by page and visit.
- Repeated promotions are deduplicated across pages and input searches. The first returned version provides the output's search context; later overlapping records do not overwrite the version delivered in that run.
- Each search scope stores up to 50,000 listing observations. Capacity limits are reported explicitly. A new tracker can repeat old listings.
- Runs sharing a tracker name use an exclusive lease. An overlapping run may fail with a message to wait; after a crash, allow the lease to expire before retrying.
- Output and page checkpoints are separate operations. A sudden crash can repeat part of a page after restart. Use `listingId` and `observedAt`/event fields for downstream reconciliation; exactly-once delivery is not promised.
- Very large searches can hit protective request limits. Review SUMMARY for `maxItems`, `pageLimit`, `paginationReset`, `repeatedListings` or source errors. A successful bounded run does not imply a complete market export.
- Cloud reliability and actual usage must be benchmarked for your searches before relying on a schedule.

### Support

Include the search URL, run ID and coverage-summary entry when reporting a problem. This Actor is independent of BizQuest and does not contact sellers, submit inquiries or provide business valuations.

# Actor input Schema

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

Paste up to 20 BizQuest business search URLs, including category, location or price filters. Individual listing detail URLs are not supported.

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

Global maximum listing or change rows returned across all searches. Unchanged monitored listings do not count.

## `mode` (type: `string`):

Export current listings, or return new-to-tracker listings and asking-price changes from the scanned search window.

## `stateKey` (type: `string`):

Reuse this name and the same search URLs on scheduled monitoring runs. Choose a new name to reset. Only used in monitoring mode.

## `maxPagesPerSearch` (type: `integer`):

Limit the search window and the cost of checks that find no changes. Deeper pages are not monitored unless included in this limit.

## `includeSellerContacts` (type: `boolean`):

Include available seller or broker names, phone numbers and company names. No email enrichment or contact requests.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.bizquest.com/businesses-for-sale/"
    }
  ],
  "maxItems": 50,
  "mode": "snapshot",
  "stateKey": "default",
  "maxPagesPerSearch": 5,
  "includeSellerContacts": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "startUrls": [
        {
            "url": "https://www.bizquest.com/businesses-for-sale/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("piotrv1001/bizquest-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 = { "startUrls": [{ "url": "https://www.bizquest.com/businesses-for-sale/" }] }

# Run the Actor and wait for it to finish
run = client.actor("piotrv1001/bizquest-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 '{
  "startUrls": [
    {
      "url": "https://www.bizquest.com/businesses-for-sale/"
    }
  ]
}' |
apify call piotrv1001/bizquest-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,piotrv1001/bizquest-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/rmZOpwO2au1p2UPEJ/builds/2daXvBfTe4rdXVp2O/openapi.json
