# Zillow Rentals Scraper 💰 From $1.4/1K · Apartment Rent Ranges (`memo23/zillow-rentals-scraper`) Actor

Scrape Zillow rentals by city, ZIP code or URL. Apartment buildings and single rentals in one run, with address and coordinates; a complex found by search also carries its rent range. Floor plans, amenities and leasing contact with property details on. Past the 500-result cap.

- **URL**: https://apify.com/memo23/zillow-rentals-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Real estate, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🔑 Zillow Rentals Scraper

Scrape **Zillow rentals** by city, ZIP code, or URL. Apartment buildings and single-home rentals come back in the same run with address and coordinates; a building found by a search also carries its rent range in `Rent Min` and `Rent Max`.

One row per listing, as JSON, CSV, or Excel. An apartment complex is one row for the whole building, with its floor plans under `floorPlans`.

### ⭐ Why use this Zillow rentals scraper?

- **Buildings and houses together** — a rentals search mixes apartment complexes with individual homes. Both are returned, in the same columns.
- **The rent range, not one number** — a complex prices per floor plan, so each complex a search returns carries `Rent Min` and `Rent Max` beside `Price`, the headline figure Zillow itself shows as "$1,449+".
- **Past the 500 cap** — turn on **Scrape beyond 500 results limit** and raise **Max Items** (default 100), and a dense city is split into smaller map areas so the search is not silently truncated.
- **Leasing contact** — the building phone number and the listing agent where Zillow exposes one, with details switched on.
- **Agent email enrichment (optional)** — with **Enrich with the agent's contact email** and **Include property details** both on, a single-home rental's listing agent is matched against a 1,200,000+ US agent database for a direct email and phone; apartment-complex rows take the building path and are not enriched.
- **Proxies included on paid plans** — on any paid Apify plan the run goes out through the actor's own residential pool at no extra cost, and the **Proxy configuration** input is not read. Free-plan runs use whatever you set there, and Zillow refuses search requests from Apify's default datacenter proxy — which is what you get by leaving it empty — so set Apify RESIDENTIAL or your own residential URLs.

### 📋 What data does it extract?

| Field group | Columns |
| --- | --- |
| **Identity** | `URL`, `Address`, `City`, `State`, `Latitude`, `Longitude` — on a default run `ID` and `Zip Code` arrive empty on apartment-complex rows, which Zillow returns as cluster pins; **Include property details** fills both from the building record |
| **Rental** | `Price` (the search card's own figure), `Rent Min` and `Rent Max` on rows a search returned, `Status` — plus `Property Subtype` with **Include property details** on |
| **People** | `Agent Name`, `Agent Number`, `Broker Name`, `Broker Number` — on single-home rentals, with **Include property details** on; an apartment complex has no listing agent of its own, so those four stay empty and its leasing phone arrives with the building record. **Enrich with the agent's contact email** adds `contactEmail`, `contactPhone` and `agentEmailSource` |
| **Optional depth** | With **Include property details** on: `details` — the full record on a single-home rental; an apartment complex spreads its building record across the row instead, with floor plans under a top-level `floorPlans` key |

### 🧾 Supported inputs

| Input | Example |
| --- | --- |
| City | `Austin, TX` |
| ZIP code | `78704` |
| Rentals search URL | `https://www.zillow.com/austin-tx/rentals/` |
| Building page | `https://www.zillow.com/apartments/austin-tx/the-janis/CqW86G/` |

A pasted building page has no search card behind it, so that row carries the building's `floorPlans` and a `Price` taken from the cheapest plan, but no `Rent Min` / `Rent Max`.

### 💡 Use cases

- **Property managers** — track competing rents per floor plan across the submarkets you operate in.
- **Investors** — compare asking rents against purchase prices to sanity-check yield before buying.
- **Relocation & corporate housing** — build a shortlist for a city with the real rent range per building.
- **Proptech & data teams** — feed rental inventory into apps, maps, CRMs, or rent indices.
- **Market research** — watch rent ranges move month to month by scheduling the same search.

### 🚀 How it works

The location is resolved to Zillow's own region and queried with `forRent` through the search API. With **Include property details** on, apartment entries are then followed to the building record, so the floor-plan list and amenities land on the row; a default run keeps the search-level columns, which already carry the rent range. With **Scrape beyond 500 results limit** on, a search over 500 matches is split into map quadrants, which takes it far past the cap; the split stops at a depth limit, so a very dense area can still be truncated.

### ⚙️ Input configuration

| Field | Type | Notes |
| --- | --- | --- |
| `searchLocation` | array | City, neighborhood or ZIP, one per line |
| `startUrls` | array | Or paste a Zillow rentals URL or a building page. The filters above are not applied to a pasted URL |
| `status` | enum | `forRent` by default; switch to `forSale` or `sold` for the same search over other listing types |
| `moreResults` | boolean | Split dense searches past the 500-result cap |
| `priceMin` / `priceMax` | integer | Monthly rent range |
| `bedsMin` / `bathsMin` | integer | Minimums |
| `homeTypes` | array | Apartment, house, condo, townhouse, … |
| `includePropertyDetails` | boolean | Adds the full record, amenities and contacts per row |
| `flatOutput` | boolean | A location search needs `includePropertyDetails` on too; a pasted property or building URL is flattened either way. A single-home rental row then drops the nested blob and gains beds, baths, sq ft and the other flat columns |
| `enrichEmails` | boolean | Agent email and phone from the agents database, on single-home rental rows; a location search needs `includePropertyDetails` on too, a pasted `/homedetails/` URL does not. On a `/profile/` agent URL in `startUrls` it discovers an email from the agent's own site instead. Billed per email found |
| `maxItems` | integer | Stop after this many rentals; 100 by default |

Every field, with its type and default, is also listed on the actor’s own [input schema page](https://apify.com/memo23/zillow-rentals-scraper/input-schema).

### 📦 Output sample

```json
{
  "URL": "https://www.zillow.com/apartments/austin-tx/bellrock-la-frontera/CtqCKn/",
  "Address": "16304 Fm 1325, Austin, TX",
  "City": "Austin",
  "State": "TX",
  "Latitude": 30.475164,
  "Longitude": -97.68957,
  "Price": 1309,
  "Rent Min": 1125,
  "Rent Max": 2040,
  "Status": "FOR_RENT"
}
```

### 🔑 Key output fields

- `Rent Min` / `Rent Max` — the floor-plan range for a building, read off the search card, so they are on rows a search returned. A single-home rental carries one figure in `Price` and no range; a building page pasted into **Start URLs** carries no range either — read its `floorPlans` for the per-plan rents.
- `Price` — the price carried on the search card itself, which is not always the floor of the range: the sample row's card says 1309 while its cheapest floor plan is 1125. Read `Rent Min` for the floor. Only when a complex's card carries no price of its own does `Price` fall back to the lowest floor-plan rent, and it then equals `Rent Min`.
- `Status` — `FOR_RENT` on a rentals sweep.
- `Property Subtype` — the building's structure type, such as `MULTI_FAMILY`. Zillow's `buildingType` sometimes holds a listing status (`FOR_RENT`) instead of a type; those rows read `APARTMENT_BUILDING`. Where the record carries no building or home type at all, the column stays empty. It is filled from the building record, so it needs **Include property details** on and is empty otherwise.
- `details` — the full record on a single-home rental, with **Include property details** on. An apartment complex instead carries its building record at the top level of the row, with floor plans under `floorPlans` — each plan with its own beds, baths and rent.

Column names are Title Case (`Address`, `Zip Code`, `Rent Min`) so they read cleanly as spreadsheet headers.

### ❓ FAQ

**Is `Price` the cheapest floor plan?**
Not necessarily. A building has no single rent, and the column carries the figure on Zillow's own search card — 1309 on the sample row above, against a 1125 floor. The full span is in `Rent Min` and `Rent Max`.

**Can I get individual units?**
Floor plans, with their own beds, baths and rent, arrive with the building record when **Include property details** is on, under a top-level `floorPlans` key on the complex's row. A building page pasted into **Start URLs** carries them without the toggle.

**Why are amenities and the leasing contact missing?**
They come from the building record, which is only fetched with **Include property details** on. A default run stays fast and returns the search-level columns.

**Can I use it for sale listings too?**
Yes — switch `status` to `forSale` or `sold` and the same search runs over those.

**I asked for a whole city and got exactly 500 rows.**
Turn on **Scrape beyond 500 results limit**. Without it, Zillow's own cap stops the search at 500 and the rest is never served.

**Why did a run stop early?**
Usually **Max Items**, which defaults to 100 — raise it and the sweep keeps going. The other cause is the "Maximum cost per run" limit; when that is what cut the run short, the run says so in its status message.

**Do I need proxies or an API key?**
No API key, and no login is used. On a paid Apify plan the actor's own residential proxies are included at no extra cost and the proxy input is not read. On the free plan the run uses Apify's default datacenter proxy, which Zillow refuses, so set **Proxy configuration** to Apify RESIDENTIAL or your own residential URLs.

### 🛟 Support

Open an issue on the actor's **Issues** tab with the run ID and the listing that looked wrong — that is enough to trace it.

### 🧩 Additional services

Need a custom pipeline (specific columns, delivery to your DB/S3/webhook, merged multi-source feeds)? Open an issue describing what you need or contact the author through the actor page.

### 🔎 Explore more scrapers

Eleven Zillow actors, all maintained by the same author. The six under **Listings and properties** share the same standard columns as this one, so rows from any of them line up in one sheet — a variant can add columns on top, as this one adds `Rent Min` and `Rent Max`. The four under **People and contacts** are separate scrapers with their own columns.

**Listings and properties**

- [Zillow Scraper](https://apify.com/memo23/zillow-scraper-ppe) — the flagship: search by city, ZIP or filters, for sale, for rent, sold, plus change monitoring.
- [Zillow Detail Scraper](https://apify.com/memo23/zillow-detail-scraper) — the full record for specific properties, by URL, ZPID or plain address.
- [Zillow ZIP Code Search Scraper](https://apify.com/memo23/zillow-zip-code-search-scraper) — sweep a list of ZIP codes instead of one area at a time.
- [Zillow Open Houses Scraper](https://apify.com/memo23/zillow-open-houses-scraper) — upcoming open houses with their exact dates and times.
- [Zillow Foreclosure Scraper](https://apify.com/memo23/zillow-foreclosure-scraper) — pre-foreclosure, auction and bank-owned (REO) records with auction dates and amounts.
- [ZILLOW | Bypass Limit of 500 | Search |Agent | with Email](https://apify.com/memo23/zillow-cheerio-scraper) — the earlier search build, kept in step with the flagship, with agent email enrichment.

**People and contacts**

- [Zillow Agents Leads](https://apify.com/memo23/zillow-agents-leads-scraper-ppe) — agent contacts pulled from a database of 1,200,000+ US agents.
- [Zillow Agents Scraper](https://apify.com/memo23/apify-zillow-agents-cheerio) — agent finder and profile pages, with email discovery.
- [Zillow Property Managers Scraper](https://apify.com/memo23/apify-zillow-property-managers-cheerio) — property managers and owners, with emails.
- [Zillow Lenders Scraper](https://apify.com/memo23/zillow-lenders-scraper) — mortgage lenders from Zillow’s own lender directory.

Beyond Zillow: [all actors by memo23](https://apify.com/memo23), 100+ maintained scrapers for real estate, jobs, directories and reviews.

### 🤖 For AI Agents & LLM Apps

This actor is MCP-ready: call it from AI agents (Claude, GPT, LangChain, LlamaIndex, or the Apify MCP server) to answer questions like *"what two-bedroom apartments rent for under $2,000 in Austin right now?"*. The rent range is explicit in `Rent Min` / `Rent Max`, so an agent can reason about affordability without parsing a price string.

To wire it up: the ready-made [Node.js](https://apify.com/memo23/zillow-rentals-scraper/api/javascript) and [Python](https://apify.com/memo23/zillow-rentals-scraper/api/python) client snippets call this actor in a few lines, the [MCP tab](https://apify.com/memo23/zillow-rentals-scraper/api/mcp) exposes it as a tool to an MCP client, and once you have run the actor you can wire its [Integrations tab in your own Apify Console](https://console.apify.com/actors/08AizTfgEmlm3fnM4/integrations/options) to push each run straight to Google Sheets, Slack, a webhook or your own storage ([how integrations work](https://docs.apify.com/integrations)).

### ⚠️ Disclaimer

This actor is not affiliated with, endorsed by, or connected to Zillow Group. It extracts only publicly visible listing information for lawful purposes such as market research and personal planning; no login is used and no private data is accessed. You are responsible for how you use the data — respect Zillow’s terms and applicable laws. Apify’s own write-up on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting point, and personal data in the output (agent names, phone numbers, emails) falls under rules such as [EU Regulation 2016/679](https://eur-lex.europa.eu/eli/reg/2016/679/oj).

***

*zillow rentals scraper · scrape zillow apartments · zillow rent data extractor · apartment rent range scraper · zillow for rent listings · zillow rentals API · rental market data · export zillow rentals to excel*

# Actor input Schema

## `searchLocation` (type: `array`):

One location per line — "Austin, TX", "Brooklyn, NY" or a ZIP such as 78704. Each becomes its own search, using the Listing status below (For rent by default).

## `startUrls` (type: `array`):

Zillow URLs to scrape as written. Accepts a search URL, a /homedetails/ property, a /b/ or /apartments/ building, a /community/ page, or a /profile/ agent page — the type is auto-detected. The filters above are not applied to these URLs: what the URL itself asks for is what you get, so paste a rentals URL if you want rentals. Example: https://www.zillow.com/austin-tx/rentals/

## `status` (type: `string`):

For rent by default. Switch to For sale or Recently sold to run the same locations over those listing types. Applies to the locations above; a URL in Start URLs keeps whatever listing type it already carries.

## `moreResults` (type: `boolean`):

Zillow limits search results to 500 properties per query. Enable this option if your search has more than 500 results. The scraper automatically splits the search area into smaller map areas, which takes the run far past the 500 cap. The split stops at a depth limit, so a dense enough area can still be truncated. Note: This process may take longer and consume more resources.

## `priceMin` (type: `integer`):

Lowest monthly rent to include — or lowest price, if you switched Listing status to For sale or Recently sold.

## `priceMax` (type: `integer`):

Highest monthly rent to include — or highest price, if you switched Listing status to For sale or Recently sold.

## `bedsMin` (type: `integer`):

Minimum bedrooms.

## `bathsMin` (type: `integer`):

Minimum bathrooms.

## `homeTypes` (type: `array`):

Limit to specific property types. Leave empty for all.

## `includePropertyDetails` (type: `boolean`):

Off by default. Follows every search row to its own Zillow page and adds the full record: the listing agent and broker, and a `details` object with Zillow's complete property data. An apartment complex is followed to its building page instead, which spreads the building record across the row with its floor plans under `floorPlans`. This toggle is also what makes the extra Flattened output columns and the email enrichment below reachable. A default run skips it and keeps the search-level columns, which already carry the rent range.

## `flatOutput` (type: `boolean`):

On a location search it needs Include Property Details on as well, since there is nothing to flatten until a detail page is fetched; a pasted property, building, community or agent URL is flattened either way. With both on, a single-rental row drops the nested `details` blob and gains flat scalar columns instead: Listing Date, Days on Zillow, Year Built, Status, Beds, Baths, Sq Ft, MLS ID, MLS Status, Annual Tax, Price History, New Roof flag and Permit History. Easier to import into spreadsheets. An apartment-complex row takes the building path, which has no detail fetch, so it only loses its photo arrays.

## `enrichEmails` (type: `boolean`):

On a location search it needs Include Property Details on as well, because the match runs during the detail fetch; a pasted /homedetails/ property URL is fetched as a detail page anyway and needs no other toggle. Where it runs, a single-rental row gains the listing agent's email and phone in contactEmail + contactPhone, matched from our database of 1,200,000+ U.S. agents, ~99.9% of which have an email on file. An apartment-complex row takes the building path and is never enriched. Billed per email found; only charged when an email is returned, never for misses. (On a /profile/ agent URL in Start URLs it instead discovers a contact email from the agent's own website, and needs no other toggle.)

## `maxItems` (type: `integer`):

Maximum number of items to scrape.

## `maxConcurrency` (type: `integer`):

Maximum number of pages that can be processed at the same time. Anything above 32 is capped to 32 — the HTTP client crashes beyond roughly that many parallel sockets.

## `maxRequestRetries` (type: `integer`):

Number of times the crawler will retry a failed request before giving up.

## `proxy` (type: `object`):

On a paid Apify plan this input is ignored: the actor routes every request through its own residential proxy at no extra cost to you. On the free plan the run uses whatever you set here, and Zillow refuses search requests coming from Apify's default datacenter proxy — which is what you get by leaving this empty — so pick Apify Proxy with the RESIDENTIAL group, or enter your own residential proxy URLs.

## Actor input object example

```json
{
  "searchLocation": [
    "Austin, TX"
  ],
  "status": "forRent",
  "moreResults": false,
  "includePropertyDetails": false,
  "flatOutput": false,
  "enrichEmails": false,
  "maxItems": 100,
  "maxConcurrency": 20,
  "maxRequestRetries": 5
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {
    "searchLocation": [
        "Austin, TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/zillow-rentals-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 = { "searchLocation": ["Austin, TX"] }

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

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

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

```

## CLI example

```bash
echo '{
  "searchLocation": [
    "Austin, TX"
  ]
}' |
apify call memo23/zillow-rentals-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/zillow-rentals-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/08AizTfgEmlm3fnM4/builds/PZSIgUUYcUeJxzgoq/openapi.json
