A rental market only tells you something when you watch it. One snapshot of Los Angeles listings is trivia. The same query every week for three months is a trend you can act on.
The awkward part has always been the collection. Here is the short version.
Start from a search URL, not a query language
The scraper takes the Zillow URL you already have:
curl -X POST "https://api.apify.com/v2/acts/parseforge~zillow-rentals-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"listingUrl": "https://www.zillow.com/los-angeles-ca/rent",
"maxItems": 200
}'
That is the whole input. Filter on Zillow until the map shows what you want, copy the URL out of the address bar, and paste it in. Beds, baths, price bands and the drawn boundary all survive, because the filters live in the URL.
Build the series, not the snapshot
One run gives you current listings. A series needs a date attached, and the runs to be comparable.
- Freeze the query. Same
listingUrlevery week. Change the filters and you are measuring your filters, not the market. - Stamp each run. Every dataset carries the run that produced it, so the date comes for free. Keep the dataset id with the rows.
- Store rows, not averages. Compute the median later. Averaging at collection time throws away the distribution, and the distribution is where the interesting movement usually is.
The number worth watching
Median asking rent moves slowly and lags. Two things move sooner:
- Listing count. Supply arriving or drying up shows up here first.
- Time on market, if you track when a listing first and last appeared. That needs your own bookkeeping across runs, which is why storing raw rows matters.
Scope
Public listing pages only. Nothing behind a login, and no contact details for agents or owners.