# BizBuySell & BizQuest Deal Change Monitor (`nickatnite79/bizbuysell-bizquest-deal-change-monitor`) Actor

Monitor new business listings and changes to asking price, cash flow and revenue. Saved buyer searches produce structured alerts with original source links.

- **URL**: https://apify.com/nickatnite79/bizbuysell-bizquest-deal-change-monitor.md
- **Developed by:** [Nicholas Tamagni](https://apify.com/nickatnite79) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $140.00 / 1,000 deal change alerts

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

## BizBuySell & BizQuest Deal Change Monitor

Monitor saved buyer searches across BizBuySell and BizQuest. Receive newly observed listings, asking-price reductions or increases, and cash-flow, revenue, or EBITDA changes as structured JSON with the original listing links.

The first successful run creates a baseline and returns matching listings. Later runs return matching changes. An unchanged scan can correctly produce an empty alert dataset; its observed listings and source health remain available.

### Start a saved search

1. Set your location, industry, price range, and minimum cash flow. For a narrow search, paste the marketplace's search URLs into `sourceUrls`.
2. Keep a stable `searchId` and `stateStoreName` so later runs reuse the same baseline.
3. Start with three listings per source and detail enrichment enabled. Check **Run health and coverage** and the original source links.
4. Save the input as an Apify Task. Add a daily or weekly Apify Schedule, leaving enough time between runs for the previous scan to finish.

Example buyer input:

```json
{
  "searchId": "texas-restaurants",
  "stateStoreName": "buyer-deal-monitor-state",
  "sources": ["bizbuysell", "bizquest"],
  "location": "Texas",
  "industry": "Restaurants",
  "maxAskingPrice": 750000,
  "minCashFlow": 100000,
  "includeUnknownFinancials": false,
  "emitInitialListings": true,
  "fetchDetails": true,
  "maxListingsPerSource": 3,
  "bizbuysellCollector": "parseforge",
  "bizquestCollector": "memo23",
  "providerMaxChargeUsd": 1,
  "providerTimeoutSecs": 180
}
```

A cash-flow threshold excludes records whose cash flow is unknown. `includeUnknownFinancials: true` allows those financially unverified records through financial thresholds. Listing limits apply before local filtering, so a strict search can yield fewer matches than the limit.

Changing search criteria or source URLs creates a separate baseline. Supported category-search routes preserve their scope separately from the listing's disclosed industry; categories are never inferred from promotional prose. For other categories, supply the marketplace search URL and leave the local `industry` filter blank when the listing's category is unavailable.

### Results and delivery

| Output | What it contains |
| --- | --- |
| **Deal change alerts** | Default dataset: one event per changed matching listing, including all financial changes |
| **Run health and coverage** | Source status, collection limits, provider runs, and whether monitoring state was preserved |
| **Observed listings** | Normalized observations from this run, including nonmatching records |
| **Saved search settings** | Search criteria and original source URLs |

#### Example output

One real alert from run `FTE6B7UJMdwmInhcX` (Oct 13, 2026), trimmed to the main fields:

```json
{
  "eventType": "new_listing",
  "searchId": "review-0401cf56",
  "observedAt": "2026-10-13T18:41:27.167Z",
  "listingId": "bizbuysell:2507134",
  "listing": {
    "source": "bizbuysell",
    "url": "https://www.bizbuysell.com/business-opportunity/established-30-year-commercial-plumbing-and-hvac-company/2507134/",
    "title": "Established 30+ Year Commercial Plumbing & HVAC Company",
    "location": "Williamson County, TX",
    "askingPrice": 8500000,
    "cashFlow": 1178697,
    "revenue": 6500000,
    "ebitda": null
  },
  "previous": null,
  "current": {
    "askingPrice": 8500000,
    "cashFlow": 1178697,
    "revenue": 6500000,
    "ebitda": null
  },
  "changes": {}
}
```

Each alert includes `schemaVersion`, a deterministic `eventId`, `eventType`, `searchId`, `scopeKey`, `runId`, observation timestamps, the source-scoped `listingId`, and a `listing` object with an original `url`. `previous` and `current` hold asking price, cash flow, revenue, and EBITDA. `changes` supplies previous/current values, delta, and percent change for affected fields. `previous` is `null` on a newly observed listing.

Event types are `new_listing`, `price_reduced`, `price_increased`, `financial_changed`, `entered_search`, and `left_search`. Financial values are numeric USD or `null`. Undisclosed or inaccessible values stay unknown; EBITDA is separate from cash flow. Source-scoped duplicates are combined. Listings on different marketplaces retain both source links because shared business identity is not guaranteed.

Use Apify's dataset JSON or CSV export, API, or integrations to consume the alerts. An Apify run-success webhook can notify your delivery system; configure a failure notification as well. Consumers should deduplicate by `eventId`, because interrupted delivery can be replayed. The Actor does not send email itself.

### Pricing and spending limits

The monitor's launch pricing is **$140 per 1,000 delivered change alerts ($0.14 each)**, plus **$0.05 per monitoring run**. An unchanged run incurs the run fee and collection costs, with no change-alert fees. Six delivered alerts cost $0.89 in monitor fees.

**Collector fees are additional.** The default workflow calls [ParseForge's BizBuySell collector](https://apify.com/parseforge/bizbuysell-scraper-v2/pricing) and [Memo23's BizQuest collector](https://apify.com/memo23/bizquest-scraper/pricing) using the running account. Their current pricing, plan discounts, and optional detail charges apply separately. Check those pricing pages for current rates; the monitor's displayed alert price does not include them.

`providerMaxChargeUsd` defaults to **$1 for each source's collector run**. Both sources therefore allow up to $2 in child Actor charges per scan; this is a cap, not a price quote or a complete account budget. The parent monitor's maximum charge is a separate limit. Keep listing caps small, and increase the parent limit when increasing the number of possible alerts. Insufficient alert capacity is rejected before collection. Paid runs use the provider collectors and a fixed 512 MB parent allocation.

Scheduled runs consume account credits even when no changes are found. Choose an interval and caps that fit your account budget. Your own scheduled searches are monitoring expenses; earnings come from other paid-plan customers using this Actor.

### Monitoring limits

Scans capped at three listings per source are a small sample, not complete marketplace coverage. A listing first appearing within the observed sample is newly observed by this search; that does not establish its marketplace publication date.

A failed, blocked, or incomplete scrape cannot establish that a listing was removed. Removal detection is disabled. A source failure preserves its monitoring history, and a complete source failure makes the run fail visibly. Unknown financial figures never become zero.

Financial figures are marketplace/provider observations supplied by sellers, not audited financial statements. Check the original listing before making an acquisition decision. Source access and provider output can change.

The tested workflow collected both marketplaces, persisted the same saved search across runs, and returned no repeated alerts for unchanged observations. A controlled test with deliberately simulated previous values verified price and financial-change delivery; it was not evidence of an actual market change.

# Actor input Schema

## `searchId` (type: `string`):

Stable name for this saved search; changing criteria creates a separate baseline.

## `location` (type: `string`):

State or city and state, e.g. Texas or Houston, TX. State names and abbreviations match. Unsupported routing falls back to a capped broad scan; exact sourceUrls are recommended.

## `industry` (type: `string`):

Match disclosed industry/category words. Known industries such as Restaurants generate verified category search routes; when an individual industry is unavailable, that verified source category scope may satisfy the filter. Unknown categories are never inferred from descriptions.

## `minAskingPrice` (type: `integer`):

Optional minimum disclosed asking price.

## `maxAskingPrice` (type: `integer`):

Optional maximum disclosed asking price.

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

Optional minimum disclosed cash flow/SDE. EBITDA is a separate field and never substituted.

## `includeUnknownFinancials` (type: `boolean`):

Allow null financials through price/cash-flow thresholds. They remain null and must be verified independently.

## `sources` (type: `array`):

Select BizBuySell, BizQuest, or both. Established Apify collectors are used by default; native HTTP collection remains available.

## `sourceUrls` (type: `array`):

Optional HTTPS URLs copied from either marketplace. Search URL query filters are preserved. URLs must correspond to the selected sources. These override generated search URLs.

## `emitInitialListings` (type: `boolean`):

When disabled, the first successful scan establishes a silent baseline; listings first observed on later runs are still delivered.

## `fetchDetails` (type: `boolean`):

Enrich listings with publicly disclosed cash flow, revenue and EBITDA when available. Undisclosed or inaccessible fields remain unknown.

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

Selected proxy settings for Memo23 and optional native HTTP collection. The verified Memo23 detail test used Apify residential proxy. Proxy traffic may add platform cost. ParseForge manages its own browser/proxy.

## `maxListingsPerSource` (type: `integer`):

Maximum distinct listings scanned per source, before local filters. Capped scans report partial coverage.

## `maxPagesPerSource` (type: `integer`):

Maximum successfully parsed search pages per source.

## `maxConcurrency` (type: `integer`):

Maximum concurrent detail requests for each source.

## `minRequestIntervalMillis` (type: `integer`):

Minimum time between request starts to each source, including retries.

## `requestTimeoutSecs` (type: `integer`):

HTTP timeout for each attempt.

## `maxRetries` (type: `integer`):

Retries for timeouts, rate limits, and server failures. Access denial is recorded without repeated attempts.

## `stateStoreName` (type: `string`):

Named key-value store reused across runs. Keep this stable; the per-run default store cannot maintain monitoring history.

## `bizbuysellCollector` (type: `string`):

The verified ParseForge collector uses its own supported browser. It is billed separately by Apify; current Free pricing is up to $0.19 per enriched listing. Native requests may be blocked.

## `bizquestCollector` (type: `string`):

The verified Memo23 collector supports public listing details. It is billed separately by Apify. Native HTTP supports accessible search cards.

## `providerMaxChargeUsd` (type: `number`):

Apify pay-per-event charge cap for each selected provider run. With both sources, provider caps can total twice this value. Parent Actor compute/storage and provider platform usage may be additional. Check provider pricing before increasing limits.

## `providerTimeoutSecs` (type: `integer`):

Each child collector run is bounded by this timeout. Failed or unfinished provider runs do not become empty successful scans.

## Actor input object example

```json
{
  "searchId": "default",
  "location": "",
  "industry": "",
  "includeUnknownFinancials": false,
  "sources": [
    "bizbuysell",
    "bizquest"
  ],
  "sourceUrls": [],
  "emitInitialListings": true,
  "fetchDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "maxListingsPerSource": 3,
  "maxPagesPerSource": 1,
  "maxConcurrency": 1,
  "minRequestIntervalMillis": 1000,
  "requestTimeoutSecs": 20,
  "maxRetries": 0,
  "stateStoreName": "biz-deal-monitor-state",
  "bizbuysellCollector": "parseforge",
  "bizquestCollector": "memo23",
  "providerMaxChargeUsd": 1,
  "providerTimeoutSecs": 180
}
```

# Actor output Schema

## `events` (type: `string`):

New listings and price/financial changes with previous/current values and original source URLs.

## `summary` (type: `string`):

Always inspect source health. A blocked scrape is a failure and cannot establish that a listing disappeared.

## `snapshot` (type: `string`):

Raw normalized observations from this run for benchmarking, including nonmatching listings and unobserved fields.

## `search` (type: `string`):

Run search criteria and source URLs. Proxy settings and credentials are omitted.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nickatnite79/bizbuysell-bizquest-deal-change-monitor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nickatnite79/bizbuysell-bizquest-deal-change-monitor").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 '{}' |
apify call nickatnite79/bizbuysell-bizquest-deal-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nickatnite79/bizbuysell-bizquest-deal-change-monitor"
        }
    }
}
```

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/wygkrPIpFPicH3V2G/builds/VS0c9X6oXgW8iwCRi/openapi.json
