DEV Community

Devil Scrapes
Devil Scrapes

Posted on

BizQuest listings: the anchors lie, the JSON-LD doesn't

Quick answer

The BizQuest Business-for-Sale Scraper turns BizQuest, the US small-business marketplace, into a deduplicated table of businesses for sale: headline, teaser, asking price in USD, city or county, state code and name, lead photo, listing URL, and three card tags (Financing Available, Includes Real Estate, SBA Loan Eligible). Scrape the nationwide feed, a state (Texas, TX) or a city (Houston, TX), or paste a BizQuest URL. BizQuest has no export. Pricing is pay-per-result, $0.20 per run plus $0.006 per listing, $6.20 per 1,000 listings.

Does BizQuest have an API or export?

Not a public one. The site shows about fifty businesses per page and expects you to click through. The Actor walks the listing pages for every route you choose and returns one row per business, with the route, page and position each row was found at so you can trace any figure back to the page it came from.

Why do we read the JSON-LD and ignore the page links?

Because the links lie. BizQuest repeats listing ids in sidebar widgets, and its result list mixes in franchise advertisements and broker promo cards that look like listings. If you collect every anchor on the page you get duplicates and things that are not businesses for sale.

On a BizQuest results page the reliable list of businesses is the inline JSON-LD, not the anchors: the anchors repeat ids from sidebar widgets.

So the parser reads the page's SearchResultsPage JSON-LD list and keeps an entry only if its URL has the shape of a real listing (/business-for-sale/<slug>/BW<id>/). Franchise ads and broker cards have a different URL shape and are dropped. The tags are not in the JSON-LD, so they are read from the server-rendered card for the same BW id.

What else we handle

  • Out-of-range pages clamp to page 1. Ask BizQuest for a page past the end and it serves page 1 again. A page whose listings were all already seen on that route ends the route, so you are never charged for page 1 twice.
  • One dedupe set for the whole run. The same listing id never appears twice, across pages or across routes (nationwide plus Texas overlap heavily).
  • Cash flow and EBITDA are gated. BizQuest shows them only to signed-in visitors. Rather than guess, rows carry financialsGated, which is true when the card says "Sign In to View".
  • Undisclosed prices stay null. askingPrice is a whole-dollar integer, or null, never 0.
  • A blocked route doesn't end the others. The run fails only if a route was blocked and nothing at all was collected.

What the Actor gives you

One row per business, 18 fields: listingId, url, title, description, askingPrice, currency, locality, state, stateName, financialsGated, financingAvailable, includesRealEstate, sbaEligible, imageUrl, searchRoute, pageNumber, position and scrapedAt.

{
  "listingId": "2540957",
  "url": "https://www.bizquest.com/business-for-sale/private-gym/BW2540957/",
  "title": "Private gym",
  "description": "Members-only fitness club offering 24-hour gym access.",
  "askingPrice": 400000,
  "currency": "USD",
  "locality": "Monument",
  "state": "CO",
  "stateName": "Colorado",
  "financialsGated": true,
  "financingAvailable": false,
  "includesRealEstate": false,
  "sbaEligible": false,
  "searchRoute": "/businesses-for-sale/",
  "pageNumber": 1,
  "position": 1,
  "scrapedAt": "2026-10-12T08:00:00Z"
}
Enter fullscreen mode Exit fullscreen mode

Input: includeNationwide (default on), locations, startUrls, maxPages (default 3, up to 200, about 50 listings per page) and maxItems (default 150, up to 10,000).

Honest limitations 🚧

Search-card fields only: no detail pages, broker contact details or confidential financials, and no cash flow, EBITDA or revenue. Query-string filters on a pasted URL are dropped, so paste the route you want. BizQuest serves up to about 200 pages for the nationwide feed. A route with no listings is a successful run that costs only the start fee.

FAQ

Do I need a BizQuest account or API key?
No. The Actor reads public listing pages.

What about blocks?
That's our job. We rotate curl-cffi browser fingerprints (Chrome, Firefox, Safari), retry with exponential backoff and Retry-After, up to 5 attempts per page, and rotate US residential Apify Proxy sessions on every block.

Why did I get fewer rows than maxItems?
The route has fewer listings than your cap, or maxPages stopped the run first. The status message says which.

How does pricing work?
$0.20 per run plus $0.006 per unique listing: $6.20 per 1,000 listings.

→ BizQuest Business-for-Sale Scraper on Apify


Built by Devil Scrapes. We handle the fingerprints, the proxies and the retries, and we keep franchise ads out of your deal flow. 😈

Top comments (0)