# Zillow Price Tax History Scraper (`kawsar/zillow-price-tax-history-scraper`) Actor

Property price and tax history scraper that outputs one flat row per event. Every sale, price change, and tax year becomes its own dataset record, ready to load into a spreadsheet or database without any post-processing.

- **URL**: https://apify.com/kawsar/zillow-price-tax-history-scraper.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

<p align="center">
  <img src="https://i.imgur.com/o7H5Ye1.png" alt="Zillow Price & Tax History Scraper" />
</p>

## Zillow Price & Tax History Scraper, Flat Row-Per-Event Property Data Extraction

Most property data tools give you one blob of JSON per address. This actor works differently. Every price change, every sale, every tax year becomes its own row in the dataset. Load the results straight into a spreadsheet or database and you can sort by date, filter by event type, and calculate year-over-year trends without touching the data first.

### Who this is for

Real estate investors who want to screen deals fast. Researchers building housing market datasets. Data teams who need property transaction history in a format that works with SQL, Excel, or any BI tool without a transformation step in the middle.

### What you get

Two types of rows, both in the same dataset:

**Price event rows** cover every transaction and listing event on record for a property — sales, listings, price reductions, pending sales. Each row has the date, dollar amount, price per square foot, percentage change from the prior event, event label, MLS source, and agent names when available.

**Tax record rows** cover annual property tax history. Each row has the tax year, annual tax paid, year-over-year tax change as a percentage, assessed value, and assessed value change as a percentage.

All rate fields from the source are converted to plain percentages. There are no decimal fractions to convert on your end.

### Input

Three ways to look up a property. Mix and match in any combination.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `zpidIds` | array of strings | — | Property IDs, one per line |
| `listingUrls` | array of strings | — | Listing page URLs, one per line |
| `addressQueries` | array of strings | — | Full street addresses, one per line |
| `timeoutSecs` | integer | 300 | Total run time limit in seconds. Increase for larger batches. |

At least one of the first three is required. You can mix all three in a single run.

#### Setting timeout for larger batches

The default 300 seconds works for small runs. For bigger lists you need to increase `timeoutSecs` — and set the same value in your Apify actor run settings under **Timeout**:

| Properties | Recommended `timeoutSecs` |
|-----------|--------------------------|
| up to 10 | 300 |
| up to 30 | 1000 |
| up to 50 | 1800 |
| up to 100 | 3600 |
| 100+ | 3000 per 100 properties |

If the run hits the limit mid-batch, the actor stops cleanly and saves everything collected so far. It logs a warning so you can see exactly where it stopped and re-run with the remaining inputs.

#### How URL lookup works

Both of these URL formats are accepted without any change on your end:

````

https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131\_zpid/
https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734

````

The first has the property ID in the path. The actor pulls it out directly. The second does not — the actor reads the address slug from the URL and resolves the property ID automatically before fetching history. Same output either way.

#### Example input

```json
{
    "zpidIds": ["58187131", "20482366"],
    "listingUrls": [
        "https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131_zpid/"
    ],
    "addressQueries": ["4315 Lago Viento, Austin, TX 78734"]
}
````

### Output

One record per property, not one record per event. All price events and tax records are spread across flat numbered columns on a single row. A batch of 50 properties produces 50 rows, each up to 90 columns wide.

#### Sample output record

This is what a real record looks like. Each property produces exactly one row like this, with price events in `price1*` through `price10*` columns and tax records in `tax1*` through `tax10*` columns. Columns for entries that do not exist are simply absent.

```json
{
    "inputQuery": "4315 Lago Viento, Austin, TX 78734",
    "propertyId": "58187131",

    "price1Date": "2026-02-11",
    "price1Amount": 1299000,
    "price1PerSqft": 281,
    "price1Change": -1.96,
    "price1Event": "Listed for sale",
    "price1Source": "Unlock MLS",
    "price1Buyer": null,
    "price1Seller": null,

    "price2Date": "2023-09-20",
    "price2Amount": 685000,
    "price2PerSqft": 249,
    "price2Change": -7.65,
    "price2Event": "Sold",
    "price2Source": "ACTRIS",
    "price2Buyer": "Shelly Martinez",
    "price2Seller": "Shelly Martinez",

    "price3Date": "2023-08-17",
    "price3Amount": 741500,
    "price3PerSqft": 269,
    "price3Change": 0,
    "price3Event": "Listed for sale",
    "price3Source": "ACTRIS",
    "price3Buyer": null,
    "price3Seller": null,

    "price4Date": "2022-04-08",
    "price4Amount": 741500,
    "price4PerSqft": 269,
    "price4Change": 8.25,
    "price4Event": "Sold",
    "price4Source": "ACTRIS",
    "price4Buyer": null,
    "price4Seller": "Jordan Whitfield",

    "tax1Year": 2025,
    "tax1Amount": 14820,
    "tax1TaxChange": 3.62,
    "tax1AssessedValue": 612000,
    "tax1ValueChange": 2.15,

    "tax2Year": 2024,
    "tax2Amount": 14302,
    "tax2TaxChange": -1.34,
    "tax2AssessedValue": 598800,
    "tax2ValueChange": 8.71,

    "tax3Year": 2023,
    "tax3Amount": 14496,
    "tax3TaxChange": 4.88,
    "tax3AssessedValue": 550800,
    "tax3ValueChange": -3.22,

    "tax4Year": 2022,
    "tax4Amount": 13821,
    "tax4TaxChange": 6.14,
    "tax4AssessedValue": 569200,
    "tax4ValueChange": 21.43,

    "fetchedAt": "2026-04-17T10:32:00Z"
}
```

#### Field naming pattern

| Pattern | Description |
|---------|-------------|
| `inputQuery` | The exact value you passed in — ID, URL, or address |
| `propertyId` | Resolved property ID |
| `price{n}Date` | Date of price event n |
| `price{n}Amount` | Price in USD |
| `price{n}PerSqft` | Price per square foot |
| `price{n}Change` | Percentage change vs. the prior event. Negative = price dropped. |
| `price{n}Event` | Event label: Sold, Listed for sale, Price change, Pending sale, etc. |
| `price{n}Source` | MLS or data source name |
| `price{n}Buyer` | Buyer agent name when disclosed |
| `price{n}Seller` | Seller agent name when disclosed |
| `tax{n}Year` | Tax year |
| `tax{n}Amount` | Annual property tax paid in USD |
| `tax{n}TaxChange` | Year-over-year change in tax paid as a percentage |
| `tax{n}AssessedValue` | Assessed value in USD |
| `tax{n}ValueChange` | Year-over-year change in assessed value as a percentage |
| `fetchedAt` | ISO 8601 timestamp of when the record was retrieved |
| `error` | Only present when the fetch failed after all retry attempts |

### How the actor processes each input

1. **Property ID** — goes straight to history lookup, no extra step.
2. **URL with ID in path** — ID is extracted from the URL, no extra request.
3. **URL without ID** — address slug is pulled from the path and used to resolve the property ID first, then history is fetched.
4. **Street address** — property ID is resolved from the address first, then history is fetched.

Once the property ID is confirmed, the actor fetches up to 10 price events and 10 tax records. Everything goes into one flat record per property — price events as `price1*` through `price10*` columns, tax records as `tax1*` through `tax10*` columns. Rate fields are converted to plain percentages. Agent objects are flattened to name strings.

### When something goes wrong

Every request retries up to 5 times. Wait time between retries: 1 second, 2, 4, 8. If all five fail, the actor writes a single error row for that property — with `error` and `inputQuery` filled in — and keeps going with the rest of the list. You can identify failed lookups by filtering for rows where the `error` field is not empty.

# Actor input Schema

## `zpidIds` (type: `array`):

Zillow property IDs, one per line. Each ID produces its own set of rows in the output.

## `listingUrls` (type: `array`):

Listing page URLs, one per line. URLs with or without a property ID in the path are both supported.

## `addressQueries` (type: `array`):

Full property addresses, one per line. The property ID is looked up automatically before fetching history.

## `timeoutSecs` (type: `integer`):

How long the actor is allowed to run in total. Default 300 seconds works for small batches. For larger lists set this higher — around 30 seconds per property is a safe estimate (50 properties = 1500, 100 properties = 3000). Must also match the run timeout set in your Apify actor settings.

## Actor input object example

```json
{
  "zpidIds": [
    "58187131",
    "20482366"
  ],
  "listingUrls": [
    "https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131_zpid/"
  ],
  "addressQueries": [
    "4315 Lago Viento, Austin, TX 78734"
  ],
  "timeoutSecs": 300
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "zpidIds": [
        "58187131",
        "20482366"
    ],
    "listingUrls": [
        "https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131_zpid/"
    ],
    "addressQueries": [
        "4315 Lago Viento, Austin, TX 78734"
    ],
    "timeoutSecs": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/zillow-price-tax-history-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "zpidIds": [
        "58187131",
        "20482366",
    ],
    "listingUrls": ["https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131_zpid/"],
    "addressQueries": ["4315 Lago Viento, Austin, TX 78734"],
    "timeoutSecs": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/zillow-price-tax-history-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "zpidIds": [
    "58187131",
    "20482366"
  ],
  "listingUrls": [
    "https://www.zillow.com/homedetails/4315-Lago-Viento-Austin-TX-78734/58187131_zpid/"
  ],
  "addressQueries": [
    "4315 Lago Viento, Austin, TX 78734"
  ],
  "timeoutSecs": 300
}' |
apify call kawsar/zillow-price-tax-history-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kawsar/zillow-price-tax-history-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Zillow Price Tax History Scraper",
        "description": "Property price and tax history scraper that outputs one flat row per event. Every sale, price change, and tax year becomes its own dataset record, ready to load into a spreadsheet or database without any post-processing.",
        "version": "0.0",
        "x-build-id": "1GX84cKCLaiqeMhN0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kawsar~zillow-price-tax-history-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kawsar-zillow-price-tax-history-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/kawsar~zillow-price-tax-history-scraper/runs": {
            "post": {
                "operationId": "runs-sync-kawsar-zillow-price-tax-history-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/kawsar~zillow-price-tax-history-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-kawsar-zillow-price-tax-history-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "zpidIds": {
                        "title": "Property ID(s)",
                        "type": "array",
                        "description": "Zillow property IDs, one per line. Each ID produces its own set of rows in the output.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "listingUrls": {
                        "title": "Listing URL(s)",
                        "type": "array",
                        "description": "Listing page URLs, one per line. URLs with or without a property ID in the path are both supported.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "addressQueries": {
                        "title": "Address(es)",
                        "type": "array",
                        "description": "Full property addresses, one per line. The property ID is looked up automatically before fetching history.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "timeoutSecs": {
                        "title": "Timeout (seconds)",
                        "minimum": 60,
                        "maximum": 86400,
                        "type": "integer",
                        "description": "How long the actor is allowed to run in total. Default 300 seconds works for small batches. For larger lists set this higher — around 30 seconds per property is a safe estimate (50 properties = 1500, 100 properties = 3000). Must also match the run timeout set in your Apify actor settings.",
                        "default": 300
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
