Understanding data

What Can You Learn from an Off-Market Zillow Property?

A field-by-field checklist for researching a known home that is not listed: what the estimates, sale history, facts and leftover listing details can tell you, and what they cannot.

7 min read

Start with a home you already know about

Most homes are not for sale on any given day, and Zillow still keeps a page for many of them. If you already have an address or a Zillow link for such a home, a lookup returns what that page shows: Zillow's estimates, past sales and listings, tax years, physical facts and sometimes details left over from the last listing.

That makes an off-market lookup useful for research on a property you have a reason to study, such as a neighbor's home in a comparison you are assembling yourself, a property a client asked about, or a home in your own portfolio. It does not find off-market homes for you. The API looks up properties you supply; it has no search across homes that are not listed, and it returns no owner names, owner contact details or signals that an owner wants to sell.

Recognize an off-market response

An unlisted home usually comes back with homeStatus OTHER, sometimes OFF_MARKET, and statusText Off market. Check this before reading any price field, because it changes what the other fields mean.

price is normally null for these homes. When the source page fills its price slot with the Zestimate for an unlisted home, the API returns null instead, so you never see an estimate disguised as an asking price. A null price here is the correct answer, not a gap to fill.

Status can also change between your lookup and the moment someone reads your notes. A home that was off market last month may be listed today, and a home that looked listed may have been withdrawn. Keep the collection time with the review sheet, and look the home up again before any decision that depends on whether it is for sale.

The field-by-field checklist

Work through the fields in this order. Each row says what the field can tell you about an off-market home and the limit you should write next to it.

FieldWhat it tells youLimit
homeStatus, statusTextThe home is not listed on the sourceNot a statement about the owner's plans
zestimate, rentZestimateZillow's current estimates, when shownEstimates, not offers or appraisals. Can be null
calculated.last_sale_price and last_sale_dateThe most recent recorded saleNull price when the sale was not disclosed
lastSoldPrice, dateSoldThe source's last sale fieldsPrefer the dated Sold event when they differ
priceHistoryPast listings, removals, rentals and salesOnly events the source shows; gaps are normal
taxHistory, taxAnnualAmountTax paid and assessed value by yearAssessed value is not market value
beds, baths, livingArea, lotSize, yearBuilt, homeTypePhysical facts as shownMay predate renovations or additions
parcelId, schoolsParcel number and nearby schoolsUse the parcel number with the county record
description, photos, agentName, brokerNameContent from a past listing, if anyStale by definition; not current contacts
daysOnZillowA day count from the sourceNot days on market; calculated.days_on_market is null

Leftover listing details are history, not news

In one recorded test response for an off-market home, the description, photos and listing agent came from past listings, and the newest event in priceHistory was a Listing removed entry dated more than a year before the lookup. Nothing in those fields was wrong, but none of it described the home's current state.

Read the last Listing removed or Sold event in priceHistory and treat everything listing-shaped as belonging to that moment. An agent named on an old listing represented a past seller or landlord. They are not the owner, and the response gives you no basis to contact them about the home today. Photos from an old listing remain the photographer's or broker's, and the data-rights page explains why we return photo links rather than copies.

Estimates and change since the last sale

For an unlisted home, the calculated change_since_last_sale_pct compares the most recent sale with the Zestimate, and change_since_last_sale_basis says zestimate. That is a comparison of a past sale with Zillow's current estimate. It is useful for context and should be labeled exactly that way, not as appreciation the owner could realize.

If the Zestimate is null, the change is null too. The null Zestimate guide explains why estimates go missing and how to show that without inventing a number.

Generate the review sheet

The script reads one saved response and prints each checklist item with its caveat attached, so the limits travel with the values when you paste the sheet into a report. It warns if the home turns out not to be off market, finds the latest Listing removed event, and prints unavailable for missing values instead of zero.

Save the response first. The lookup costs the same as any other: one credit for a successful live lookup, free for a repeat inside the cache window and free when it fails.

off_market_review.py
"""off_market_review.py: a field-by-field review sheet for one known, off-market home."""
import json, sys

NOT_LISTED = {"OTHER", "OFF_MARKET"}

def latest(events, label):
    hits = [e for e in events or [] if (e.get("event") or "").lower() == label]
    return max(hits, key=lambda e: e.get("date") or "", default=None)

def review(body):
    d, meta = body["data"], body["meta"]
    calc = d.get("calculated") or {}
    events = d.get("priceHistory") or []
    out = []
    def add(item, value, caveat):
        out.append((item, "unavailable" if value is None else value, caveat))

    if d.get("homeStatus") in NOT_LISTED:
        add("Status", d.get("statusText") or d.get("homeStatus"),
            "Not listed on the source page. Says nothing about whether the owner would sell.")
    else:
        add("Status", d.get("statusText") or d.get("homeStatus"),
            "WARNING: this home is not off market; use a listing review instead.")
    add("Current asking price", d.get("price"), "Normally unavailable for an unlisted home.")
    add("Zestimate", d.get("zestimate"), "Zillow's estimate, not an offer or appraisal.")
    add("Rent Zestimate", d.get("rentZestimate"), "Zillow's monthly rent estimate.")
    add("Last sale", calc.get("last_sale_price"),
        f"Most recent Sold event, dated {calc.get('last_sale_date') or 'unknown'}; null if undisclosed.")
    removed = latest(events, "listing removed")
    add("Last listing removed", removed and removed.get("date"),
        "The most recent listing ended here. Its text and photos may still appear.")
    fact = lambda k: "?" if d.get(k) is None else d.get(k)
    add("Facts", f"{fact('beds')} bd / {fact('baths')} ba / {fact('livingArea')} sqft / built {fact('yearBuilt')}",
        "As shown by the source; may predate renovations.")
    add("Tax history years", len(d.get("taxHistory") or []), "Assessment, not market value.")
    add("Listing agent on record", d.get("agentName"),
        "From a past listing if present. Not the owner, and not a current contact for this home.")
    add("Days on Zillow", d.get("daysOnZillow"),
        "For an unlisted home this is not days on market; calculated.days_on_market is null.")
    add("Collected", meta.get("fetched_at"), "Re-check the source page before acting.")
    return out

if __name__ == "__main__":
    body = json.load(open(sys.argv[1], encoding="utf-8"))
    print(body["data"].get("address"), "|", body["data"].get("detailUrl"))
    for item, value, caveat in review(body):
        print(f"- {item}: {value}\n    {caveat}")

# Save one response, then review it
curl --get "https://api.propertiesapi.com/v1/zillow/property" \
  --header "x-api-key: $PROPERTIESAPI_KEY" \
  --data-urlencode "address=$PROPERTY_ADDRESS" \
  --max-time 130 -o home.json
python off_market_review.py home.json

What not to infer

Off-market data invites guesses, so it helps to write the forbidden inferences down. A rising Zestimate does not mean the owner will sell. A long gap since the last sale does not mean a home is ready to list. A removed listing does not mean it failed to sell for a reason you can name. An old agent record is not a lead.

What you can say is narrower and more useful: what the home is, what it last sold for if that was disclosed, how its taxes and Zillow's estimates look today, and when you collected those facts.

  • Do not present the home as available or likely to sell.
  • Do not treat past listing contacts as owner contacts.
  • Do not fill a null price with the Zestimate.
  • Keep the collection time and the source link with every saved review.

Sources and documentation

Product details checked against the linked documentation on October 22, 2026. Code and sample inputs are illustrative unless stated otherwise.

Written by PropertiesAPI, an independent property data service. We are not affiliated with Zillow. Source data may be incomplete or change over time.