Zillow Sold Comps Scraper: Comparable Sales & ARV avatar

Zillow Sold Comps Scraper: Comparable Sales & ARV

Pricing

from $1.30 / 1,000 comp saveds

Go to Apify Store
Zillow Sold Comps Scraper: Comparable Sales & ARV

Zillow Sold Comps Scraper: Comparable Sales & ARV

Get sold comps from Zillow for any US address: the most similar recent sales nearby with sale price, $/sqft, days on market and a similarity score, plus a comp-based value estimate. ARV for flips, list prices in non-disclosure states.

Pricing

from $1.30 / 1,000 comp saveds

Rating

0.0

(0)

Developer

Epic Scrapers

Epic Scrapers

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

3 days ago

Last modified

Share

Zillow Sold Comps Scraper: comparable sales and ARV for any address

Zillow Sold Comps Scraper finds the best comparable sales for a home in seconds. Give it an address, a Zillow link or a zpid, and it returns the most similar homes sold nearby recently, ranked by a similarity score, with sale price, $/sqft, days on market, sale-to-list ratio and the value each comp indicates for your property. Every property also gets a comp-based value estimate with a low–high range.

Built for real estate investors, wholesalers and flippers, agents preparing a CMA, appraisers, lenders, iBuyer-style underwriting, and AI agents that need a comp check as a tool.

  • Real comps, not a city dump. Comps are picked around your property the way an appraiser would: same home type, sold in the last 6 months, within a mile, similar size and bedrooms. Every rule can be changed.
  • Ranked by similarity. Each comp gets a 0–100 score from distance, living area, sale date, bedrooms, bathrooms, age and lot size, plus its differences from your property (bedroomsDiff, livingAreaDiff, …) for an adjustment grid.
  • A value estimate per property. The median value indicated by the comps ($/sqft × your living area), with a 25th–75th percentile range. Outliers such as a luxury penthouse among garden condos are flagged and left out.
  • After-repair value (ARV) in one line. Add | 3 bd, 2 ba, 1700 sqft (or | +1 bd, +400 sqft) after an address, and it comps the home as it will be after the renovation. Put the line in with and without it to see the uplift.
  • Works in Texas and other non-disclosure states. Zillow hides sale prices there. This scraper reads the last asking price before each sale from the price history and uses it (clearly marked) so you still get $/sqft and an estimate.
  • Never too few comps. When the radius has too few sales, it widens automatically (1 → 2 → 3 miles by default) and still ranks the closest first.
  • Bulk and fast. Hundreds of addresses in one run, 3 properties in parallel. 30 properties with 10 comps each took 68 seconds in our tests.
  • API- and agent-ready. Plain JSON in, flat rows out. Call it from the Apify API, Make, Zapier, n8n, or any AI agent through the Apify MCP server.
  • Pay per comp, no subscription. About 2 cents for 10 comps. No Zillow account, API key or proxy setup. Export to JSON, CSV, Excel or Google Sheets.

Scope: This Actor is built around one property at a time. For every home sold, listed or rented in a city or ZIP code, use Zillow Scraper or Zillow ZIP Code Search Scraper.

Contents

What can you do with it?

GoalHow
Comp a property for an offerAdd the address, keep the defaults. Read estimatedValue in the Valuation summary and check the top comps.
ARV for a flipAdd the planned facts after a |: 123 Main St, Austin, TX 78704 | 3 bd, 2 ba, 1700 sqft.
Underwrite a deal listPaste all addresses. Every property gets its comps and an estimate in one run.
Screen listings for a discountComp homes for sale and compare listPrice with estimatedValue in the summary.
Prepare a CMA for a listingSet maxComps to 5–6 and turn on includeDetails for photos, descriptions and agents.
Check pricing in a fast marketSet soldWithinDays to 90 and rankBy to recent; look at saleToListRatio and daysOnMarket.
Track a portfolio's valueSave the addresses as a task and schedule it monthly. Compare estimatedValue per zpid between runs.
Rural or unusual homesRaise radiusMiles to 3–5 and soldWithinDays to 365, set livingAreaMatch to 40.
Give an AI agent a comp toolConnect the Apify MCP server with this Actor as a tool. See AI agents.

How it compares

What you needZillow Sold Comps ScraperArea-wide sold scrapersZillow's "similar homes sold" listComping by hand on Zillow
Starts from your propertyYes: address, URL or zpid, on or off marketNo, a city or ZIP listYesYes
Your comp criteriaRadius, sold within, type, beds, baths, sqft, year builtCity or ZIP filtersNone, Zillow picksManual
Ranked by similarity0–100 score and differences per compNoNoYour judgment
Value estimate and rangeYes, with outliers removedNoNoSpreadsheet work
ARV after repairsYes, one lineNoNoManual
Texas and non-disclosure statesLast list price before the sale, markedSales without a priceVariesPrice hidden
Hundreds of propertiesOne runOne run per areaOne property at a timeHours

Quick start

  1. Click Try for free and sign in to Apify.
  2. Add one or more properties: 1916 N 46th St, Seattle, WA 98103, a Zillow property URL or a zpid.
  3. Keep the default comp criteria for a first run.
  4. Click Start. Open the Output tab: Comparable sales has the comps, Valuation summary the estimate per property.
{
"subjects": ["1916 N 46th St, Seattle, WA 98103", "https://www.zillow.com/homedetails/119624861_zpid/"],
"maxComps": 10
}

After-repair value (ARV)

Write the home's facts after the work behind a | on its line. Anything you leave out stays as Zillow has it.

You writeMeaning
| 3 bd, 2 ba, 1700 sqft3 bedrooms, 2 bathrooms, 1,700 sqft after repairs
| +1 bd, +0.5 ba, +400 sqftAdd a bedroom, a half bath and 400 sqft to Zillow's facts
| 4 beds 3 baths 2,200 sq ft built 2026Also sets the year built (for a rebuild)
| duplex, | townhome, | houseChanges the home type (e.g. a conversion)

Common spellings work: 3bd, 3 beds, 3-bed, 3BR/2BA, 1500sf, 1,500 sq ft. Words the scraper doesn't understand (such as new roof) are reported in the log and the rest of the line is still used. The Valuation summary shows each change as asIs → afterRepair, and each comp row carries the text in subjectAfterRepair.

As-is value and ARV of a 2-bed townhome renovated into a 3-bed with 1,700 sqft, in one run:

{
"subjects": ["1916 N 46th St, Seattle, WA 98103", "1916 N 46th St, Seattle, WA 98103 | 3 bd, 1700 sqft"],
"maxComps": 5
}

In a test run this home comped at $863,000 as it is (Zestimate $794,600) and $1,100,000 after the planned work, from five 3-bedroom sales of 1,640–1,844 sqft within 0.35 miles.

The value follows mostly the living area: more bedrooms on the same area picks comps with more bedrooms, but the estimate moves with their $/sqft. Add the square feet you are adding, too.

Input reference

FieldTypeDefaultEffect
subjectsArray of stringsRequiredUS street addresses, Zillow property URLs or zpids, one per entry. On or off the market. Add | … for ARV.
maxCompsInteger10Comps per property, best first (1–100).
includeDetailsBooleanfalseAdds description, all photos, agent contacts, price and tax history, schools and 150+ facts to each comp. Charged as a separate event per comp.
soldWithinDaysInteger180Only sales from the last N days (1–1,095). Filters by sale date.
radiusMilesNumber1Search radius around the property (0.05–25).
expandRadiusBooleantrueDouble the radius up to maxRadiusMiles when too few sales match.
maxRadiusMilesNumber3The widest the search may go.
sameHomeTypeBooleantrueHouses with houses, condos with condos, townhomes with townhomes.
bedroomsMatchString"1""exact", "1", "2" or "any" (± bedrooms).
bathroomsMatchString"1""exact", "0.5", "1", "2" or "any" (± bathrooms).
livingAreaMatchString"25""10", "15", "20", "25", "30", "40", "50" or "any" (± percent).
yearBuiltMatchString"any""5", "10", "20", "30" or "any" (± years).
rankByString"similarity""similarity" (0–100 score), "recent" (newest sale first) or "closest".
onlyPricedCompsBooleantrueSkip sales without any price. Skipped sales are not charged.
useListPriceWhenUndisclosedBooleantrueIn non-disclosure states, value with the last asking price before the sale, marked valuationBasis: "lastListPrice".

Note that the match fields are strings, not numbers: "livingAreaMatch": "40". Invalid lines (a ZIP code, a city page URL, text without a house number) are skipped with a message in the log and the run summary, and the rest of the run goes on.

Ready-to-run examples

Underwrite a deal list

{
"subjects": [
"1916 N 46th St, Seattle, WA 98103",
"https://www.zillow.com/homedetails/119624861_zpid/",
"7775469",
"114407255"
],
"maxComps": 6
}

Open the Valuation summary and sort by estimatedValue minus listPrice (or your offer) to find the best margins.

Loose comps for a rural property

{
"subjects": ["https://www.zillow.com/homedetails/119624861_zpid/"],
"radiusMiles": 3,
"maxRadiusMiles": 10,
"soldWithinDays": 365,
"livingAreaMatch": "40",
"yearBuiltMatch": "20"
}

Strict comps for an appraisal-style grid

{
"subjects": ["1916 N 46th St, Seattle, WA 98103"],
"maxComps": 6,
"radiusMiles": 0.5,
"maxRadiusMiles": 1,
"soldWithinDays": 90,
"bedroomsMatch": "exact",
"bathroomsMatch": "0.5",
"livingAreaMatch": "15",
"yearBuiltMatch": "10",
"includeDetails": true
}

Use the Adjustment grid view: one row per comp with its differences from the property, the price used and the indicated value.

Fast-market check: what sold in the last 90 days

{
"subjects": ["1916 N 46th St, Seattle, WA 98103"],
"maxComps": 20,
"soldWithinDays": 90,
"rankBy": "recent"
}

Read medianSaleToListRatio and medianDaysOnMarket in the summary.

Run at scale

  • Batch size. There is no fixed limit on subjects. Properties run 3 at a time; plan on roughly 2–3 seconds per property with 10 comps. For thousands, split into runs of a few hundred so one bad batch is easy to rerun.
  • Cap the cost. Set Maximum cost per run in the run options (maxTotalChargeUsd in the API). The scraper plans its work against the budget, saves what it covers and stops cleanly; it never charges past the cap.
  • Keep runs cheap. includeDetails costs more than the comp itself; turn it on only for the properties you will look at closely. onlyPricedComps (on by default) means you never pay for a comp that can't value the property.
  • Join the outputs. Every comp row starts with subjectInput, subjectZpid and subjectAddress, and carries subjectEstimatedValue, so the dataset alone is enough for most spreadsheets. The low–high range and medians are in the SUMMARY record, one entry per input in input order, with an input field to match.
  • Schedule it. Save your input as a task (Save as a new task), then add it to a schedule in Schedules (for example 0 6 1 * *, monthly) to track a portfolio's values. Connect Google Sheets, Make, Zapier, n8n or a webhook in the task's Integrations tab.
  • Errors don't stop the run. A property that isn't found gets an error in the summary; one with no matching sales gets a note saying what to relax. The run's status message counts both.

Use through the Apify API

Run synchronously and get the comps back in one request (good for up to a few dozen properties; synchronous runs time out after 5 minutes):

curl "https://api.apify.com/v2/acts/epicscrapers~zillow-sold-comps-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-X POST \
-H "Content-Type: application/json" \
-d '{"subjects": ["1916 N 46th St, Seattle, WA 98103"], "maxComps": 10}'

For larger batches, start the run, wait for it, and read both the comps and the valuation summary:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('epicscrapers/zillow-sold-comps-scraper').call(
{
subjects: ['1916 N 46th St, Seattle, WA 98103', '1916 N 46th St, Seattle, WA 98103 | 3 bd, 1700 sqft'],
maxComps: 10,
},
{ maxTotalChargeUsd: 1 },
);
const { items: comps } = await client.dataset(run.defaultDatasetId).listItems();
const summary = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('SUMMARY');
for (const s of summary.value) console.log(s.address, s.estimatedValue, s.estimatedValueLow, s.estimatedValueHigh);
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("epicscrapers/zillow-sold-comps-scraper").call(
run_input={"subjects": ["1916 N 46th St, Seattle, WA 98103"], "maxComps": 10},
max_total_charge_usd=1,
)
comps = client.dataset(run["defaultDatasetId"]).list_items().items
summary = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("SUMMARY")["value"]

The summary is also a plain URL: https://api.apify.com/v2/key-value-stores/<defaultKeyValueStoreId>/records/SUMMARY?token=YOUR_APIFY_TOKEN.

Use it from AI agents (MCP)

AI assistants and agents (Claude, ChatGPT, Cursor, VS Code, n8n and anything that speaks the Model Context Protocol) can call this Actor as a tool through the Apify MCP server. The agent sends an address, the Actor returns the ranked comps and the estimate, and the agent answers with the numbers.

Connect

Hosted server (OAuth sign-in, or an Authorization: Bearer YOUR_APIFY_TOKEN header), with this Actor and the storage tools enabled:

https://mcp.apify.com?tools=epicscrapers/zillow-sold-comps-scraper,storage

Claude Code:

claude mcp add --transport http apify "https://mcp.apify.com?tools=epicscrapers/zillow-sold-comps-scraper,storage" \
--header "Authorization: Bearer YOUR_APIFY_TOKEN"

Claude Desktop, Cursor and other clients with a JSON config (runs the server locally):

{
"mcpServers": {
"apify": {
"command": "npx",
"args": ["-y", "@apify/actors-mcp-server", "--tools", "epicscrapers/zillow-sold-comps-scraper,storage"],
"env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
}
}
}

The Actor shows up as the tool epicscrapers-slash-zillow-sold-comps-scraper, with this page's input schema as its parameters.

What to ask

  • "Pull sold comps for 1916 N 46th St, Seattle, WA 98103 and tell me what it's worth. Show the 5 closest comps with price, $/sqft and distance."
  • "What is the ARV of 123 Main St, Austin, TX 78704 if I add a bedroom and 400 sqft? Compare it with the as-is value."
  • "Here are 20 listings from my deal sheet. Comp each one and list the ones priced at least 10% below the estimate."
  • "Is https://www.zillow.com/homedetails/119624861_zpid/ overpriced? Compare its list price with recent sales within half a mile."

Notes for agent builders

  • Smallest useful call: {"subjects": ["<address>"], "maxComps": 5}. Keep includeDetails off: details add descriptions, photos and histories that fill the model's context and cost more.
  • One call for many homes. Pass every address in one subjects array instead of one call per address.
  • Where the answer is. Each dataset row is one comp and carries subjectEstimatedValue, so the default tool output is enough for "what is it worth". The range (estimatedValueLow/estimatedValueHigh), medians, listPrice, and the error or note of a property without comps are in the SUMMARY record of the run's key-value store; with the storage tools enabled the agent can read it.
  • No comps is not an error. A property without matching sales has no dataset rows. Read its note in SUMMARY and retry with a larger maxRadiusMiles, soldWithinDays or livingAreaMatch.
  • Say how prices were derived. When valuationBasis is lastListPrice (Texas and other non-disclosure states), the comp's price is its last asking price, not the sale price. priceOutlier: true comps are excluded from the estimate.
  • Set a budget. Give the agent a maxTotalChargeUsd per run; 10 comps cost about $0.02.

You can also hand an assistant an export: download the Adjustment grid view as CSV and ask, for example, "Adjust each comp for the bedroom, bathroom and size differences at $X per sqft and $Y per bathroom, then give me an adjusted value range."

Output

Comparable sales (dataset)

One row per comp, best first, grouped by property. Each row starts with the property it is a comp for:

FieldExample
subjectInput, subjectZpid, subjectAddress, subjectAfterRepair, subjectEstimatedValue, subjectListPrice1916 N 46th St, Seattle, WA 98103, 845000
compRank, similarityScore, distanceMiles1, 77, 0.19
bedroomsDiff, bathroomsDiff, livingAreaDiff, yearBuiltDiff0, -0.5, -300, 13 (comp minus property)
soldDate, soldPrice, salePriceDisclosed, nominalSale2026-10-09, 770000, true, false
lastListPrice, listedDate, daysOnMarket, saleToListRatio785000, 2026-08-05, 65, 0.981
valuationPrice, valuationBasis770000, soldPrice (or lastListPrice)
pricePerSqft, indicatedValue, priceOutlier720, 986400 ($/sqft × the property's living area), false
zpid, url, address, streetAddress, city, state, zipcode, latitude, longitude
homeType, bedrooms, bathrooms, livingArea, lotSize, lotSizeUnit, yearBuilttownhome, 2, 2, 1070
zestimate, rentZestimate, taxAssessedValue, taxAssessmentYear, photo, brokerName, mlsName

With includeDetails, each comp also has description, photos, listingAgent, coListingAgent, broker, priceHistory, taxHistory, schools, monthlyHoaFee, walkScore, climateRisk, facts (150+) and more.

The Output tab has two views: Comps and Adjustment grid (differences from the property, price used and indicated value). Export as JSON, CSV, Excel, XML or HTML.

Valuation summary (key-value store record SUMMARY)

An array with one entry per property, in input order:

{
"input": "1916 N 46th St, Seattle, WA 98103",
"zpid": "2137390015",
"address": "1916 N 46th St, Seattle, WA 98103",
"status": "other",
"listPrice": null,
"afterRepair": null,
"homeType": "townhome",
"bedrooms": 2,
"bathrooms": 2.5,
"livingArea": 1370,
"estimatedValue": 845000,
"estimatedValueLow": 822000,
"estimatedValueHigh": 956000,
"compsUsedForEstimate": 6,
"priceOutliers": 0,
"compsUsingListPrice": 0,
"medianPricePerSqft": 617,
"medianSoldPrice": 782475,
"medianDaysOnMarket": 54,
"medianSaleToListRatio": 0.995,
"averageDistanceMiles": 0.28,
"zestimate": 794600,
"compsSaved": 6,
"radiusMilesUsed": 1,
"soldWithinDays": 180
}

listPrice is the asking price of a property that is for sale, to compare with the estimate. Properties that could not be found have an error, and properties without matching sales a note that says what to relax.

Notes on fields

  • similarityScore is 0–100. Weights: distance 25%, living area 25%, sale recency 15%, bedrooms, bathrooms and year built 10% each, lot size 5%.
  • *Diff fields are the comp minus your property (after repairs, if given): livingAreaDiff: -300 means the comp is 300 sqft smaller.
  • soldPrice is null where the sale price is private; valuationPrice is then the last list price, and valuationBasis says which one was used.
  • nominalSale: true marks transfers under $10,000 (deed transfers, tax sales). They are never used to value.
  • radiusMilesUsed in the summary shows whether the search had to widen.
  • Missing values are null.

How the estimate works

  1. Each comp's price (sale price, or the last list price where sale prices are private) is divided by its living area.
  2. That $/sqft times your property's living area is the comp's indicatedValue.
  3. Comps far from the others in $/sqft (outside 1.5 × the interquartile range, with 4 or more comps) are flagged as priceOutlier and left out.
  4. estimatedValue is the median indicated value; estimatedValueLow and estimatedValueHigh are the 25th and 75th percentiles, rounded to $1,000. At least 3 priced comps are needed.

It is a quick, transparent $/sqft comp valuation for screening and offers, not an appraisal. Condition, views and upgrades are not priced in; use the photos and descriptions (includeDetails) to judge them.

Cost

You pay per comp saved, with no monthly fee and no start fee beyond Apify's standard one. Looking up your properties, skipped unpriced sales and the valuation summary are free.

EventFree planBronzeSilverGold and higherCharged when
comp$0.0023$0.0020$0.0017$0.0013A comp is saved.
comp-details$0.0036$0.0030$0.0024$0.0017includeDetails is on and the comp's details loaded.

Example runs:

RunFree planGold
1 property, 10 comps$0.023$0.013
1 property, 10 comps with full details$0.059$0.030
100 properties, 10 comps each$2.30$1.30
1,000 properties, 5 comps each$11.50$6.50

Set a maximum cost per run; the scraper stops before reaching it and never charges past it. The Pricing tab always shows the current prices.

Tips

  • Non-disclosure states (Texas, Utah, Idaho, Wyoming, New Mexico, Montana, Kansas, Mississippi, Louisiana, Alaska, North Dakota and some counties elsewhere): soldPrice is empty and valuationBasis is lastListPrice. List prices are usually within a few percent of the sale price, but check compsUsingListPrice in the summary.
  • Too few comps? Raise maxRadiusMiles, soldWithinDays or the tolerances. The summary's note says when nothing matched.
  • New construction can skew comps for older homes: set yearBuiltMatch to "10" or "20".
  • Wrong facts on Zillow (for example a finished basement not counted): write the correct values after a |, e.g. | 2400 sqft.

FAQ

Which homes can I comp?

Any US home Zillow knows: for sale, off market, recently sold or rented. Use the street address with city and state (or ZIP), the Zillow property URL, or the zpid.

Why is a comp missing that I see on Zillow?

It may be outside the criteria (type, size, bedrooms, date, radius), or have no price when onlyPricedComps is on.

How fast is it?

5 properties with defaults took 15 seconds; 30 properties with 10 comps each took 68 seconds. Full details add one request per comp, loaded in parallel.

Why did my run stop early?

If the log says the charge limit was reached, the run hit its maximum cost or your account's spending limit. Everything charged before that is saved. Raise the limit to collect more.

Do I need a separate scraper for details?

No. Turn on includeDetails and every comp is complete.

Can I search all sold homes in a city or ZIP code instead?

Use Zillow Scraper or Zillow ZIP Code Search Scraper for area-wide sold lists.

Do I need proxies, a Zillow account or an API key?

No. The scraper handles connections and retries itself and doesn't log in.

It collects publicly visible listing data. Agent contact details are personal data: use them lawfully (for example under CAN-SPAM, TCPA or GDPR).

Support

Report problems or request features in the Issues tab. Include the run ID, the input and what you expected. Bugs are fixed quickly.

This Actor is not affiliated with or endorsed by Zillow Group. "Zillow" and "Zestimate" are trademarks of Zillow, Inc.