Zumper Scraper - Rentals, Prices, Agents & 60+ Fields avatar

Zumper Scraper - Rentals, Prices, Agents & 60+ Fields

Pricing

from $1.20 / 1,000 listing results

Go to Apify Store
Zumper Scraper - Rentals, Prices, Agents & 60+ Fields

Zumper Scraper - Rentals, Prices, Agents & 60+ Fields

Scrape Zumper.com rental listings: apartments, houses, condos and rooms. Pulls 60+ fields per listing, including monthly rent, beds/baths, square footage, decoded amenities, agent name and phone, ratings, availability and full-resolution photos. Search by location with filters, or paste Zumper URLs.

Pricing

from $1.20 / 1,000 listing results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

2 days ago

Last modified

Share

Zumper Scraper: Rental Listings, Rent and Availability Data

Zumper Scraper turns Zumper (zumper.com), a US rental listing site, into a clean apartment, house, condo and room dataset. Search by location with rich filters, or paste your own Zumper search, building or listing links. Every record carries monthly rent, beds/baths, square footage, decoded amenities, agent name and phone, ratings, availability and full resolution photo URLs. It also monitors listings for changes across runs (NEW, UPDATED, UNCHANGED, REAPPEARED, EXPIRED), resumes an interrupted pull, and pipes results into your apps through MCP connectors.

Why This Scraper?

  • 60+ fields per listing, core data straight from the results page. Price, beds/baths, square footage, amenities, agent name, phone, rating and photos come back without turning on detail fetching.
  • Amenities decoded to plain text. Amenities and building features come back as readable labels ("In-Unit Laundry", "Fitness Center", "Garage Parking"), not opaque numeric codes.
  • Full photo URLs, not just IDs. Every image is returned as a ready to open URL.
  • Two ways to find data. Search by location and filters, or paste specific search, building or listing URLs (multiple URLs supported).
  • Availability monitoring. Scheduled runs classify every listing as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED, with per campaign state you can name or share.
  • Resume long pulls. Continue an interrupted or unbounded walk across separate runs without paying twice for what was already collected.
  • Predictable cost. A small default result cap, per record output, and an optional per listing detail surcharge only when you turn detail fetching on.

Use Cases

  • Rent trend and market research: track rent ranges, price drops and new listings across neighborhoods and cities over time.
  • Apartment hunters and relocation services: pull filtered listings (price, beds, pets) for a target city into your own site or alert tool.
  • PropTech and rental aggregators: build a secondary Zumper sourced feed with agent contacts and photos, without visiting the site by hand.
  • Investors and property managers: monitor competing buildings' pricing and availability in a submarket.
  • Lead generation for movers and brokers: watch specific buildings or listings for status changes (NEW, price change, EXPIRED) and reach out through the agent contact on the record.

Data You Get

Sample shape: values are illustrative placeholders, not from a live listing.

FieldExample
id"64606115"
urlhttps://www.zumper.com/apartment-buildings/p000000/sample-building-city-st
title"1A with Balcony"
buildingName"Sample Apartments"
propertyCategory"apartments" (also "houses", "condos", "rooms")
address"123 Sample St"
city / state / zipcode"San Francisco" / "CA" / "94103"
neighborhood"SOMA"
latitude / longitude37.7700 / -122.4000
minPrice / maxPrice4035 / 6360 (monthly rent, USD; the same names work as rent filters in both modes)
previousPrice4200 (set when the rent dropped)
minBedrooms / maxBedrooms0 / 2 (0 = studio)
minBathrooms / maxBathrooms1 / 2
minSquareFeet / maxSquareFeet509 / 980
dateAvailable"2026-01-15"
rating / externalRating9.3 / 4.1
unitAmenities["In-Unit Laundry", "Dishwasher", "Air Conditioning"]
buildingAmenities["Fitness Center", "Garage Parking", "Roof Deck"]
agentName / brokerageName / phone"Sample Mgmt" / "Sample Brokerage" / "(415) 555-0100"
primaryImage / images / imageCounthttps://img.zumpercdn.com/000000000/1280x960 / [...] / 10
shortDescription"Bright corner unit with balcony."
scrapedAt"2026-01-01T00:00:00.000Z"
changeType"NEW" (only present when incrementalMode is on, see below)
changedFields, firstSeenAt, lastSeenAtIncremental mode only

With Fetch detail pages on, a record is additionally enriched with the full description, year built and floors, amenities grouped by category, pet policy, parking, deposits, fees, specials, income restrictions, lease terms, office hours, per unit and per floorplan availability, full agent and property manager contacts, a category by category rating breakdown, and Zumper's editorial resident feedback summary. Zumper does not publish individual resident reviews (per comment text with an author and date): the rating and feedback fields above are all of the review data that Zumper itself exposes, so userReviews is always present as an empty array rather than omitted.

How to Use

  1. Pick a mode: search (build a URL from the fields below) or url (paste your own Zumper URLs).
  2. In search mode, add locations and any filters (price, beds, baths, pets); switch on Fetch detail pages if you need the fields above.
  3. Set Max listings (and optionally Max pages) to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search apartments in a city:

{
"mode": "search",
"locations": ["San Francisco, CA"],
"propertyCategory": "apartments",
"maxListings": 20
}

Search houses with filters, cheapest first, full detail:

{
"mode": "search",
"locations": ["Austin, TX"],
"propertyCategory": "houses",
"minPrice": 1500,
"maxPrice": 6000,
"minBedrooms": 2,
"petsAllowed": ["dogs"],
"sortBy": "price-asc",
"fetchDetails": true,
"maxListings": 50
}

Paste your own Zumper URLs (search results, building or listing):

{
"mode": "url",
"urls": [
"https://www.zumper.com/apartments-for-rent/new-york-ny",
"https://www.zumper.com/apartment-buildings/p000000/sample-building-san-francisco-ca"
],
"fetchDetails": true
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/zumper-scraper").call(run_input={"mode": "search", "locations": ["San Francisco, CA"], "maxListings": 20})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["title"], listing["minPrice"], listing["city"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/zumper-scraper').call({
mode: 'search', locations: ['San Francisco, CA'], maxListings: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Field availability and the dedup key

Field availability can vary by region, listing type and Zumper interface changes; use id as the idempotency / dedup key across runs. Fetch detail pages defaults to off because the results page already carries the large majority of fields; turn it on when you need the full description, ratings breakdown, units or agent records.

Both modes, one filter set

minPrice, maxPrice, minBedrooms, maxBedrooms, minBathrooms and sortBy apply in both modes: in URL mode they narrow and reorder the results of a pasted search results URL after they are read, so a pasted URL can return fewer listings than the page itself shows. A pasted building or listing URL is saved as is and is never narrowed by them; each such URL returns exactly one record (its own fields, plus units / floorplanListings for unit level detail when Fetch detail pages is on). locations, propertyCategory and petsAllowed are search only: they shape the search URL this actor builds and are not re applied to results that come back.

How Max listings shapes a run

With one location or URL, Max listings simply stops the run once that many records have been pushed. With several locations, the budget is split into an equal share per location (rounded up), and each location stops at its own share, its own last page, or the site's own end of results, whichever comes first.

Known limitation: on each results page, the number of listings attempted is sized from the remaining budget BEFORE incremental mode classifies them, and every listing on the page is marked as handled either way. If already tracked, unchanged listings sort ahead of new or changed ones on a page, the attempts can be spent on suppressed rows and the new or changed listings further down that page are silently skipped for this run (the walk moves on to the next page, or ends, and never comes back), even though the run still finishes normally. This only bites in incrementalMode with a finite Max listings (the default is 20); a non incremental run is not affected, since nothing is suppressed. Skipped new listings show up on a later run instead. Workaround: set Max listings to 0 (or well above the size of the search) on recurring monitoring runs.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice. A migration or Resurrect of a failed run also checkpoints automatically and picks back up in the same run without input.
  • Incremental mode (incrementalMode) is for scheduled runs over the same search. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that scanned the whole tracked search, and only with emitExpired). stateKey names or shares the stored state; leave it empty to derive one automatically from the location, category, filters and fetchDetails, so different searches never mix state with each other.
  • Known limitation: emitExpired rows are not subject to Max listings. Once a run qualifies to detect EXPIRED listings, every tracked listing found gone is pushed and billed, however many that is; Max listings only bounds the live NEW/UPDATED/REAPPEARED side of the same run. Budget for this on a long running campaign, or keep emitExpired off unless you want the full expired batch every time it fires.
  • Known limitation: searching several overlapping or adjoining locations in one run can end a location's walk early. If two locations return some of the same listings (a shared boundary, a duplicate feed entry), a later location can reach a results page made up entirely of listings an earlier location already returned; its walk then reads that page as a repeat and stops, even though that location has more, never seen pages left. This both drops real listings from the run and, with emitExpired on, can mark a still live listing on the unscanned pages as EXPIRED. Workaround: avoid pairing locations whose inventories are likely to overlap in one run, or run them as separate campaigns (separate stateKey).
  • Known limitation: a stateKey shared or reused across a differently scoped run can produce false EXPIRED rows. This includes deliberately sharing one stateKey between two different location, URL or search mode filter setups (in URL mode the rent, bedroom and bathroom filters are applied after reading and do not trigger this), and pasting a search URL that starts mid pagination (for example a copied ?page=3 link) under a stateKey that previously tracked the whole search: the listings that a differently scoped or later starting run never re-visits are not actually gone, but a complete-looking scan of the narrower scope will still mark them EXPIRED. Workaround: let stateKey stay empty (automatic, per scope) unless you specifically want to share state, and always paste page 1 links for a tracked campaign.
  • A monitoring campaign that is bootstrapped from a resumeFromRunId dataset (its first incremental run only; combining the two after a baseline exists fails fast with a clear message) does not suppress the listings it bootstrapped: on the next scheduled run each of them comes back as UPDATED, with every field listed in changedFields, instead of UNCHANGED. Those rows are pushed and billed like any other row (plus the detail surcharge when Fetch detail pages is on), even though you already paid for them in the resumed run; billing does not depend on the change type, so it costs the same as if they had come back NEW. After that one run they are tracked normally.
  • If the run is interrupted by a platform migration or resurrected while incrementalMode is on, listings pushed before the interruption are protected from being re-pushed or re-billed in that same run, but the automatic checkpoint saves only which listings were already handled, not their incremental classification. Their change is therefore never saved to the baseline, and on the next scheduled run they are reported (and billed) again: a listing that was NEW reads NEW again, and one that was UPDATED or REAPPEARED reads the same way again, instead of UNCHANGED.
  • Known limitation: a results page that loads but carries no readable listing data is treated as the end of that search. If Zumper changes its page layout or serves an unrecognized placeholder page, the walk stops as if the search had run out, and with emitExpired on, every tracked listing from that page onward is marked (and billed) EXPIRED even though it is still live. If a monitoring run suddenly returns a large EXPIRED batch, check whether the same search still shows those listings on the site before acting on it; they come back as REAPPEARED on the next healthy run.

Send results into your apps (MCP connectors)

Optionally pipe each scraped listing into the tools you already use (Notion, Linear, Airtable, or any Model Context Protocol server) by selecting an authorized connector in the input. Each connector receives a condensed, human readable summary per item; the complete record always stays in the dataset.

  1. Authorize a connector once under Apify -> Settings -> Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the Pipe results into your apps input field. (If the picker is empty, you have not authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (build a URL from the fields below) or url (use your own URLs).
locationsarraysampleSearch mode only. City, state, neighborhood or ZIP, multiple supported.
propertyCategorystringapartmentsSearch mode only for the category to browse. In URL mode it only labels records when the pasted URL names no category itself.
petsAllowedarray(none)Search mode only. Ask Zumper for listings that allow the selected pets (dogs, cats).
urlsarraysampleURL mode only. Zumper search, building or listing links.
minPriceinteger(none)Both modes. Minimum monthly rent (USD).
maxPriceinteger(none)Both modes. Maximum monthly rent (USD).
minBedroomsinteger(none)Both modes. Minimum bedrooms (0 = studio).
maxBedroomsinteger(none)Both modes. Maximum bedrooms.
minBathroomsinteger(none)Both modes. Minimum bathrooms.
sortBystringdefaultBoth modes. default, price-asc, price-desc, newest, rating-desc.
fetchDetailsbooleanfalseAdd full description, ratings breakdown, units/floorplans, agent contacts and more.
maxPagesinteger(none, unlimited)Result pages walked per location or URL. Leave empty to walk every page (still bounded by Max listings).
maxListingsinteger20Stop after this many listings across all searches (0 = unlimited).
resumeFromRunIdstring(none)Continue one interrupted run, or bootstrap the first run of a new incremental campaign.
incrementalModebooleanfalseTurn on for recurring monitoring of the SAME search.
stateKeystring(none)Names or shares an incremental mode state.
emitUnchangedbooleanfalseAlso return (and bill) unchanged listings.
emitExpiredbooleanfalseAlso return (and bill) listings tracked before but no longer found.
proxyobjectResidentialConnection settings; managed automatically, or supply your own proxy URLs.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

Sample shape: values are illustrative placeholders, not from a live listing.

{
"id": "64606115",
"url": "https://www.zumper.com/apartment-buildings/p000000/sample-building-city-st",
"padmapperUrl": null,
"title": "1A with Balcony",
"buildingName": "Sample Apartments",
"propertyCategory": "apartments",
"isBuilding": true,
"address": "123 Sample St",
"city": "San Francisco",
"state": "CA",
"zipcode": "94103",
"neighborhood": "SOMA",
"latitude": 37.77,
"longitude": -122.4,
"minPrice": 4035,
"maxPrice": 6360,
"previousPrice": 4200,
"currency": "USD",
"minBedrooms": 0,
"maxBedrooms": 2,
"minBathrooms": 1,
"maxBathrooms": 2,
"minSquareFeet": 509,
"maxSquareFeet": 980,
"dateAvailable": "2026-01-15",
"listedOn": "2025-12-01T00:00:00.000Z",
"modifiedOn": "2026-01-01T00:00:00.000Z",
"unitAmenities": ["In-Unit Laundry", "Dishwasher", "Air Conditioning"],
"buildingAmenities": ["Fitness Center", "Garage Parking", "Roof Deck"],
"shortDescription": "Bright corner unit with balcony.",
"rating": 9.3,
"externalRating": 4.1,
"agentName": "Sample Mgmt",
"brokerageName": "Sample Brokerage",
"phone": "(415) 555-0100",
"primaryImage": "https://img.zumpercdn.com/000000000/1280x960",
"images": ["https://img.zumpercdn.com/000000000/1280x960"],
"imageCount": 1,
"scrapedAt": "2026-01-01T00:00:00.000Z"
}

Plan Requirement

The default connection works out of the box on any Apify plan; residential connections are used by default and rotate automatically when one is refused. You may also supply your own proxy URLs in the Connection field for large or frequent runs.

FAQ

How much does it cost?

You pay per record returned, with the detail enrichment surcharge billed only when Fetch detail pages is on. The Pricing tab shows the current rates. Use Max listings to cap the cost of a run.

This actor collects only publicly available rental listing data. You are responsible for how you use it: follow Zumper's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts (rent, beds, baths, address) are generally not subject to copyright, but photos and agent supplied descriptions may carry third party rights.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared listings (plus expired ones when emitExpired is on), and unchanged ones are not billed unless you turn on emitUnchanged.

Why did my run return fewer listings than I expected?

With several locations, Max listings is split into an equal share per location, and each stops at its share or its last page, whichever comes first. Filters (price, beds, baths, pets) also narrow the result set. On a recurring, incremental run over a location with a lot of steady state (unchanged) inventory, the per page budget can also be used up on suppressed rows before reaching new ones on the same page (see "How Max listings shapes a run" above). Raise Max listings, or set it to 0, to collect more.

Why did my run finish with an empty dataset?

The run does not fail in that case: it finishes with an empty dataset (nothing is billed) and the status message "No listings returned", which covers both "no listings match this search" and "the site refused every connection". A results page that loads but carries no readable listing data is also treated as the end of that search rather than as an error. Check the log: a refused connection is logged per search. Try a different location, widen the filters, or run it again in a few minutes; supplying your own residential proxy URLs in the Connection field can also help. If only some locations or listings could be read, you still get what was found.

Does emitExpired respect Max listings?

No. Max listings caps the live NEW/UPDATED/REAPPEARED side of a run; once a run qualifies to detect EXPIRED listings, every tracked listing found gone is pushed regardless of Max listings. See the known limitation under "Resume and recurring updates" above.

Can EXPIRED ever be wrong?

In specific cases, yes: overlapping or adjoining locations searched together in one run, or a stateKey that is shared or reused across a differently scoped or differently starting run (including a pasted URL that starts mid pagination), or a results page that loads without readable listing data, can make a still live listing look unscanned this run and get marked EXPIRED. See the known limitations under "Resume and recurring updates" above for the exact triggers and the workaround.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the Pipe results into your apps field to push results into Notion, Linear or Airtable.

๐Ÿ”— Want more real estate data?

Pair this actor with these related scrapers from the same team:

๐Ÿ  Rent.com Scraper
Extract rental listings from rent.com. Get comprehensive data including monthly rent...
๐Ÿ  Trulia Scraper
Scrape Trulia.com property listings by location, filters, or URL. Extract prices, beds...
๐Ÿ  Crexi Scraper
Scrape crexi.com commercial listings: asking price, cap rate, square footage, units, year...
๐Ÿ  QuintoAndar Scraper
Scrape QuintoAndar property listings across Brazil with 80+ fields, including rent, sale...
๐Ÿ  Apartments.com Scraper
From $1.50/1K. Scrape Apartments.com rentals by city, ZIP, neighborhood, address or URL...
๐Ÿ  ImmobilienScout24.de Scraper
$0.9๐Ÿ’ฐ/1K for Gold discount. Extract property listings from immobilienscout24.de...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support & custom scrapers

  • ๐Ÿž Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • ๐Ÿ› ๏ธ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.