Documentation

Everything you need to get Zillow property data into your app, pipeline, or AI agent.

Overview

APIllow is a Zillow property data API. Send a city name, ZIP code, property ID, or Zillow URL and get back 50+ structured data fields per property — address, price, Zestimate, beds/baths, price history, tax records, school ratings, agent info, and photos.

Two ways to use it:

Authentication

All API requests require an API key passed via the X-API-Key header:

curl -H "X-API-Key: your_key" https://api.apillow.co/v1/properties

Get a free key (50 requests/month) by signing up on the homepage or through the MCP server.

Quick Start

# Search for properties in Los Angeles
curl -X POST https://api.apillow.co/v1/properties \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_key" \
  -d '{"search": "Los Angeles", "type": "sale", "max_items": 5}'

Python

import requests

resp = requests.post(
    "https://api.apillow.co/v1/properties",
    headers={"X-API-Key": "your_key"},
    json={"search": "Los Angeles", "type": "sale", "max_items": 5}
)
for r in resp.json()["results"]:
    p = r["property"]
    print(f"{p['street_address']}, {p['city']} — ${p['price']:,}")

JavaScript

const resp = await fetch("https://api.apillow.co/v1/properties", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": "your_key" },
  body: JSON.stringify({ search: "Los Angeles", type: "sale", max_items: 5 })
});
const data = await resp.json();
data.results.forEach(r => console.log(r.property.street_address, r.property.price));

POST /v1/properties

Get property data from Zillow. Accepts multiple input types in a single request.

Request Body

FieldTypeDescription
searchstringFree-text search query (e.g. "Los Angeles", "Miami Beach FL")
zipcodesint[]US ZIP codes (e.g. [90210, 90211])
zpidsint[]Zillow Property IDs
urlsstring[]Zillow listing URLs or search page URLs
typestringall (default), sale, rent, sold, fsbo
max_itemsintMax results, 1-1000 (default 200)
At least one of search, zipcodes, zpids, or urls is required. You can combine multiple in one request.

Sync vs Async

GET /v1/results/{job_id}

Poll for results from an async batch job. The status field will be "processing", "complete", or "failed".

curl https://api.apillow.co/v1/results/YOUR_JOB_ID \
  -H "X-API-Key: your_key"

Poll every 5-10 seconds until status is "complete".

Input Types

Search by city

{ "search": "Austin TX", "type": "sale", "max_items": 10 }

Search by ZIP code

{ "zipcodes": [90210, 90211], "type": "sale" }

Look up by ZPID

{ "zpids": [20794780, 20637558] }

Get data by URL

{ "urls": ["https://www.zillow.com/homedetails/123-Main-St/12345_zpid/"] }

Search page URL

{ "urls": ["https://www.zillow.com/beverly-hills-ca/"], "max_items": 20 }

Mix and match

{ "search": "Miami", "zipcodes": [33139], "type": "rent", "max_items": 50 }

Response Format

{
  "job_id": "4a021afd-c429-...",
  "status": "complete",
  "results": [
    {
      "url": "https://www.zillow.com/homedetails/.../20794780_zpid/",
      "success": true,
      "zpid": 20794780,
      "elapsed_seconds": 2.8,
      "property": {
        "street_address": "1735 N Fuller Ave APT 425",
        "city": "Los Angeles",
        "price": 379888,
        "zestimate": 374200,
        ... 50+ fields ...
      }
    }
  ],
  "errors": []
}

Data Fields

FieldTypeDescription
zpidintZillow Property ID
street_addressstringStreet address
city, state, zipcodestringLocation
latitude, longitudefloatGeocoordinates
priceintListing price (USD)
zestimateintZillow's estimated value
rent_zestimateintEstimated monthly rent
bedrooms, bathroomsint/floatBed and bath count
living_areaintInterior sqft
lot_sizefloatLot size (sqft)
year_builtintYear constructed
property_typestringSINGLE_FAMILY, CONDO, TOWNHOUSE, etc.
home_statusstringFOR_SALE, SOLD, FOR_RENT, OTHER
descriptionstringFull listing description
hoa_feefloatMonthly HOA fee
days_on_zillowintDays listed
page_view_countintZillow page views
favorite_countintTimes favorited
price_historyarrayPrice events with date, event, price, source
tax_historyarrayTax records with year, tax paid, assessed value
listing_agentobjectAgent name, phone, email, company
listing_brokerstringBrokerage name
nearby_schoolsarraySchools with rating, grades, distance
image_urlsarrayProperty photo URLs

Error Handling

HTTP CodeMeaning
200Success (check results and errors arrays)
400No valid input provided
401Invalid or missing API key
429Rate limit or monthly quota exceeded

Individual property failures appear in the errors array with details:

{
  "url": "https://www.zillow.com/homedetails/invalid/0_zpid/",
  "success": false,
  "error": "HTTP 404",
  "attempts": 3
}

MCP Server Installation

The MCP server lets AI agents (Claude, Cursor, Windsurf, etc.) access Zillow property data directly as tools.

Install

pip install apillow-mcp

Claude Desktop

Add to ~/.claude/claude_desktop_config.json:

{
  "mcpServers": {
    "apillow": {
      "command": "apillow-mcp",
      "env": {
        "APILLOW_API_KEY": "your_key"
      }
    }
  }
}

Claude Code

claude mcp add apillow -- apillow-mcp
No API key yet? The agent can create one for you — just ask it to sign up.

MCP Tools

Property Data

ToolDescription
search_properties(query, type, max_items)Search by city or area name
search_by_zip(zipcodes, type, max_items)Search by ZIP codes
get_property(zpid)Look up by Zillow Property ID
get_property_by_url(url)Get data from a Zillow listing URL

Account Management

ToolDescription
signup(email)Create free account, get API key instantly
check_usage()See current month's usage, quota, and plan
upgrade_plan(plan, email)Get a Stripe checkout URL to upgrade

Zero-Browser Signup

Users can sign up and start querying entirely through the AI agent:

# User asks their AI agent:
"Sign me up for Apillow with user@example.com"

# Agent calls signup("user@example.com") and gets:
{
  "api_key": "zs_abc123...",
  "plan": "free",
  "monthly_limit": 50
}

# Agent can immediately query:
"Find 3-bedroom homes under $500K in Austin TX"

# When they hit the limit, agent suggests upgrading:
"You've used 50/50 requests. Upgrade to Pro?"
# Agent calls upgrade_plan("pro") → returns Stripe URL

The only step requiring a browser is the Stripe payment page (PCI compliance).

Plans

PlanPriceRequests/moRate Limit
Free$0505/min
Pro$9.99/mo3,33320/min
Ultra$29.99/mo10,00060/min
Mega$99.99/mo50,000120/min

Billing API

POST /billing/signup

Create a free API key. No authentication required.

{ "email": "user@example.com" }

GET /billing/usage?api_key=your_key

Check current usage and quota.

POST /billing/checkout

Generate a Stripe Checkout URL for upgrading to a paid plan.

{ "email": "user@example.com", "plan": "pro" }

Returns a checkout_url — open in browser to complete payment.

POST /billing/webhook

Stripe webhook endpoint for subscription events. Configured in your Stripe Dashboard.