# Changelog of eBay Business Leads Scraper — Emails, VAT & Company Numbers (`programmx/ebay-business-leads`) Actor

- **URL**: https://apify.com/programmx/ebay-business-leads/changelog.md
- **Full Actor documentation**: https://apify.com/programmx/ebay-business-leads.md

## Changelog

### 0.3.0 — 2026-08-03

Cost optimization pass. All investigation done against the live site in Chrome, so the
byte measurements below cost nothing to obtain.

- **Request blocking in the browser tier.** Measured per-render wire bytes and dropped
  everything that isn't the server-rendered document or Akamai's sensor script:
  \~926 KB → ~334 KB first page, ~143 KB steady-state. Confirmed live that the trader
  block (module, email, VAT) is present in a plain fetch of the raw HTML, that search
  pages are server-rendered too, and that `/itemmodules/{id}` does *not* carry it.
  Written as a block-list, not an allow-list, because Akamai's sensor sits on a
  randomised path an allow-list would silently drop.
- **Removed the search-page hydration wait** — search results are server-rendered; only
  a short guarded fallback remains for a challenge shell.
- **Custom residential proxy** via the `CUSTOM_RESIDENTIAL_PROXY_URLS` secret env var.
  Apify residential is $8/GB against Decodo's $4/GB pay-as-you-go.
- **Warm HTTP tier** (`warmHttpTier` flag, off by default): the browser renders search
  pages and harvests the Akamai cookie set (`_abck` is HttpOnly, so it comes from
  Playwright's context), then replays it over impit on one sticky residential session
  for every item page. Falls back to the browser on failure and logs a hit rate.
- **Item→seller cache** (90-day TTL) in the existing per-task store. Caching by seller
  saves nothing — you can't consult it before the render that identifies the seller —
  so the cached edge is item→seller, which skips listings whose seller we already hold
  and collapses several listings from one wanted seller into a single render. Private
  sellers are marked permanently skippable; email-less sellers are not, since a later
  `requireEmail=false` run still wants them. No effect on a cold run; large effect on
  scheduled monitor tasks.

### 0.2.0 — 2026-08-03

Input model reworked around keyword-first targeting, after a survey of every comparable
eBay actor on the Apify store (none of which return the trader block at all).

- **Keywords are now the primary input** and the first field in the form. `startUrls` is
  retained as the advanced path — paste a pre-filtered eBay search/category URL and the
  actor inherits every filter, so the form never has to mirror eBay's own filter UI.
- **Untargeted sitemap sweep removed from the product.** A run with no keywords and no
  start URLs now fails fast instead of returning a blind list of whatever sellers a market
  happened to surface. `candidatesFromSitemaps()` stays in `src/discovery.ts`, unwired, as
  the reference implementation of eBay's only Akamai-free discovery surface.
- **New `requireEmail` input (default on)** — sellers whose trader block publishes no email
  are dropped and never billed, so the customer only pays for contactable leads. The dropped
  count is logged rather than silently swallowed.
- **Two-tier pay-per-event billing**: `unique-business-seller-with-email` (premium) for a
  contactable lead, `unique-business-seller` (base) for a verified record without one. Both
  events must exist in Console — see `docs/BUILD_NOTES.md` §1.
- `businessSellersOnly` input removed; skipping private sellers is now unconditional, since
  they carry no legally-mandated trader block and so no contact data by definition.
- `ebay.com` dropped from the domain list (no DSA trader block — it could only ever return
  empty rows). Default domain is now a single `ebay.co.uk`; `maxSellers` default 1000 → 100.

### 0.1.0 — 2026-07-31

Initial build (greenfield). TypeScript + Crawlee Apify actor.

- Two-stage, dedup-before-fetch crawl: sitemap/startUrl/keyword discovery → seller-first dedup → trader-block extraction.
- Unblocked Stage-0 discovery from eBay's public GTC (fixed-price) sitemaps.
- Tiered transport: CheerioCrawler (datacenter) with fallback to PlaywrightCrawler (residential) for Akamai-blocked listings.
- `full` and `monitor` run modes; cross-run seen-set in a named key-value store (`firstSeenAt`).
- Pay-per-event charging on `unique-business-seller`, guarded by the per-run charge limit.
- Input schema, dataset schema + Console table view, SEO README.

**Not yet validated against live business-seller pages** — trader-block selectors and block
signatures are marked `LIVE-TUNE` and must be confirmed during the Phase-1 yield gate. See
`docs/BUILD_NOTES.md`.
