How to get Zumper listings in Python
By the end of this guide you have a CSV of Austin apartments under $2,000 a month, with the leasing office's phone number, from one script you can run again tomorrow. Everything below was run on 15 October 2026; the output table is what it returned.
Why scraping Zumper yourself breaks
- Zumper has no API for reading listings. Its official integration is an inbound feed that landlords and syndication partners use to send listings to Zumper.
- Listings sent to Zumper also appear on PadMapper, so scraping both mostly returns the same apartments twice.
- Search results come from an internal JSON endpoint that takes a city path, and it changes whenever Zumper changes its website.
None of that is impossible, but each point is code you then maintain. The rest of this guide uses Listingrail, which does the reading and hands back clean JSON. The Zumper API page has the official options with sources.
1. Get a key
One request with your email returns a key with 100 free listings. It is shown once, so keep it in an environment variable.
curl -X POST https://listingrail.com/v1/signup \
-H "content-type: application/json" \
-d '{"email": "you@example.com"}'
export LISTINGRAIL_KEY=re_...2. Search and save to CSV
Install requests (pip install requests), then run:
import csv
import os
import requests
r = requests.post(
"https://listingrail.com/v1/listings/search",
headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
json={"source":"zumper","location":"Austin, TX","maxPrice":2000,"limit":50},
timeout=300,
)
r.raise_for_status()
listings = r.json()["listings"]
fields = ["price", "currency", "beds", "baths", "area", "address", "url"]
with open("zumper-austin-tx.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(fields)
for home in listings:
writer.writerow([home[k] for k in fields])
print(len(listings), "listings saved to zumper-austin-tx.csv")The request body, on its own:
{
"source": "zumper",
"location": "Austin, TX",
"maxPrice": 2000,
"limit": 50
}Each listing returned costs one credit. A search that finds nothing, or fails at Zumper, costs nothing. A request can take up to a minute or two, because Zumper is read at that moment.
3. What comes back
The first three rows of the run on 15 October 2026:
Every listing has the same keys on all 17 portals, so the code for Zumper reads the others too. Fields Zumper does not show come back as null, and the portal's own record sits in raw. With pandas:
import pandas as pd
df = pd.DataFrame(listings)
df["agent"] = df["agent"].str.get("company")
print(df[["price", "beds", "baths", "area", "address", "agent"]].head())4. Get new listings and price cuts every day
Running the script on a schedule works, but then you compare the files yourself. A monitor stores the search, checks it once a day, and sends only what changed: new listings and price cuts. The free key holds one monitor.
requests.post(
"https://listingrail.com/v1/monitors",
headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
json={
"source": "zumper",
"location": "Austin, TX",
"filters": {"maxPrice":2000},
"webhook_url": "https://example.com/new-listings",
},
timeout=30,
)Changes can also be read with GET /v1/monitors/{id}/changes or downloaded as CSV. Plans and limits are on the monitors page.
Zumper quirks worth knowing
- Pass a US city and state; it is sent as Zumper's city slug ("austin-tx").
- minPrice, maxPrice and minBeds are applied by Zumper. beds 0 is a studio.
- agent.name is usually the building or community, agent.company the management company and agent.phone its leasing office.
- area is often empty: many buildings list a price range per floor plan without square footage.
Questions
Is there a Zumper API key?
Only for landlords and partners sending listings in. Reading listings needs a third-party route such as Listingrail.
Zumper or PadMapper?
They share listings. Use one of them per city; PadMapper also covers Canada.
Can I get alerts for new Zumper listings?
Yes. A monitor checks your saved search daily and sends new listings and price cuts by webhook or CSV.