Estate Sale Scraper with Full Photo Galleries (EstateSales.net)
Pricing
from $5.00 / 1,000 results
Estate Sale Scraper with Full Photo Galleries (EstateSales.net)
Scrape estate, garage, and yard sales from EstateSales.net — with every listing's FULL photo gallery (images[]), not just one thumbnail. Nationwide, per-state, or per-ZIP. Plain-HTTP Cheerio crawling keeps cost ~10x below browser-based scrapers.
Pricing
from $5.00 / 1,000 results
Rating
5.0
(1)
Developer
Scrapelab Max
Maintained by CommunityActor stats
2
Bookmarked
3
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrape estate, garage, and yard sale listings from
EstateSales.net — including each listing's full photo gallery
(images[]), not just one thumbnail.
The scraper runs on plain HTTP requests (no headless browser at any point), which keeps its cost profile roughly 10× cheaper than browser-based scrapers (~3,000 pages per compute unit vs. ~300).
Why this scraper?
- 📸 Full photo galleries — every listing includes its complete gallery as
images[](default up to 25 photos per listing, configurable), in the site's original order. Most alternatives give you a single thumbnail. - 💰 Cheap to run — pure HTTP crawling, no browser. Zero-photo listings never trigger an extra page fetch.
- 🇺🇸 Three coverage modes — specific ZIP codes, a whole state, or every active sale nationwide.
- ✅ Fail-loud integrity — a blocked or partially-broken crawl fails the run visibly instead of silently returning an incomplete dataset.
Coverage modes
Choose exactly one per run:
| Mode | Input | What it does |
|---|---|---|
| ZIP | "zips": ["77098", ...] | Scrapes the listings around each ZIP code. |
| State | "state": "TX" | Walks every city in the state and scrapes each one. |
| Nationwide | "nationwide": true | Enumerates every currently-active sale in the US via the site's sale sitemap. |
Input
| Field | Type | Default | Notes |
|---|---|---|---|
zips | string[] | [] | ZIP codes to scrape. Ignored if state or nationwide is set. |
state | string | — | Two-letter state code (e.g. TX). Overrides zips. |
nationwide | boolean | false | Scrape every active sale in the US. Overrides zips and state. |
maxItems | number | (required) | Hard cap on emitted listings — the crawler stops cleanly the moment it's reached, so cost is always bounded. |
includeImages | boolean | true | When true, listings with photos get one detail-page fetch to collect the full images[] gallery. When false, images is [] (cheapest mode). |
maxImagesPerListing | number | 25 | Caps gallery size per listing. Truncation is logged, never silent. |
excludeTypes | string[] | [] | Sale types to drop, matched case-insensitively against each listing's type (e.g. OnlineOnlyAuctions). Empty = emit every type. |
proxyConfiguration | object | { useApifyProxy: true } | Apify proxy settings. Datacenter proxies by default. |
Example minimal input:
{ "zips": ["77098"], "maxItems": 25 }
Filtering out sale types (excludeTypes)
To skip online-only auctions, for example:
{ "zips": ["77098"], "maxItems": 25, "excludeTypes": ["OnlineOnlyAuctions"] }
Matching is case-insensitive against the site's verbatim type value. The console offers a
multi-select dropdown of the observed types: EstateSales, OnlineOnlyAuctions,
MovedOffsiteToStore, MovedOffsiteToWarehouse, and MovingSales (if the site introduces a
new type, it needs to be added to the actor's option list before it can be excluded). Every
dropped listing is counted in OUTPUT as itemsExcluded.
In ZIP/state mode the type is known from the search page, so excluded listings never consume a
maxItems slot — you still get a full maxItems of wanted listings. In nationwide mode the
sale type is only known after each detail page is fetched, so excluded listings still count
toward maxItems there: a nationwide run with excludeTypes set can report capHit: true
while emitting fewer than maxItems items (itemsEmitted + itemsExcluded accounts for the
difference).
Output
One dataset item per sale listing:
{"id": 118342,"title": "Estate Sale in Houston, TX - Antiques, Furniture & Collectibles","type": "Estate Sale","company": "Caring Transitions of Houston","address": "1234 Bissonnet St","city": "Houston","state": "TX","zip": "77098","latitude": 29.7189,"longitude": -95.42,"dates": [{ "start": "2026-07-24T09:00:00-05:00", "end": "2026-07-24T16:00:00-05:00" },{ "start": "2026-07-25T09:00:00-05:00", "end": "2026-07-25T14:00:00-05:00" }],"photo_count": 42,"main_image": "https://media.estatesales.net/img/listings/118342/main.jpg","thumbnail": "https://media.estatesales.net/img/listings/118342/thumb.jpg","is_featured": false,"url": "https://www.estatesales.net/TX/Houston/77098/118342","scrapedAt": "2026-07-21T14:32:07.418Z","images": ["https://media.estatesales.net/img/listings/118342/main.jpg","https://media.estatesales.net/img/listings/118342/img-02.jpg","https://media.estatesales.net/img/listings/118342/img-03.jpg"]}
Field guarantees:
dates[].start/endare always offset-aware ISO-8601 timestamps (never naive/local).images[0]always equalsmain_imagewhen both exist; gallery order matches the site.- Field names and types are a stable contract — new fields may be added over time, but existing ones are never renamed, removed, or retyped.
Exporting results (JSON, CSV, Excel, XML)
Every run's dataset can be downloaded in JSON, JSONL, CSV, Excel (XLSX), XML, HTML, or RSS
from the run's Storage → Export dialog, or via the
Dataset items API (?format=csv,
?format=xlsx, ...).
Two ready-made table views are included for clean flat exports:
- Sales — one row per sale (id, title, type, company, address, city, state, zip, photo count, main image, listing URL). Ideal for spreadsheets.
- Images (one row per photo) — the
images[]gallery unwound so each photo URL is its own row alongside the sale's id, title, and location. Ideal for feeding image pipelines or downloading galleries in bulk.
Select a view in the Export dialog (or pass ?view=sales / ?view=images on the API) to get
that shape in any format. Exporting without a view returns the full raw items, including the
complete images[] array and dates[] ranges.
Run integrity
The run is designed to never silently return a partial crawl:
- A search page that parses to zero listings without the site's "no sales" marker fails the run (guards against the site changing its markup under the scraper).
- A high ratio of blocked responses (403/429/challenge pages) fails the run instead of emitting a quietly incomplete dataset.
- Any request that exhausts its retries fails the run rather than dropping listings.
- Every run writes a stats object (
pagesCrawled,itemsEmitted,detailFetches,itemsExcluded,blockedResponses,parseFailures,budgetCap,budgetHit,capHit, ...) to the run'sOUTPUTkey-value store key and logs it asRun stats: {...}.
If maxItems was reached before full coverage, the run still succeeds and reports
capHit: true in OUTPUT — intentional truncation is visible, never silent.
Spending limits are honored the same way: if you set a maximum total charge on the run, the
scraper computes how many results your budget pays for, stops cleanly at that number, and
reports budgetHit: true (with the computed budgetCap) in OUTPUT — the run succeeds with
exactly the results you paid for, instead of being aborted mid-crawl by the platform. A budget
too small to pay for even one result fails the run immediately with an explanatory message.
Cost
Plain-HTTP crawling does roughly 3,000 pages per compute unit. Each listing costs at most
two page fetches (its search-results share + one detail page for the gallery), and zero-photo
listings skip the detail fetch entirely. A 25-listing ZIP run typically consumes well under
0.01 CU. Use maxItems to put a hard ceiling on any run's cost.
Etiquette
The scraper uses polite concurrency and rate limits, a browser-like User-Agent, and respects the site's robots.txt disallowed paths.