π Rental Listings Scraper β Canada, UK & USA | Geo Enriched
Pricing
from $2.00 / 1,000 listings
π Rental Listings Scraper β Canada, UK & USA | Geo Enriched
Apartments, houses, flats & rooms for rent from Kijiji + RentFaster (Canada), OpenRent (UK) and Zumper (USA) in one normalized schema: price, beds, coordinates, currency. Filters: max rent, bedrooms, keywords, near an address or subway/grocery/school. Cross-source dedup + map. Agent/MCP-ready.
Pricing
from $2.00 / 1,000 listings
Rating
0.0
(0)
Developer
Soroosh Esmaeilian
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
3
Monthly active users
7 days ago
Last modified
Categories
Share
Rental Listings Scraper β Canada π¨π¦ + UK π¬π§ + US πΊπΈ + Geo Data π
One normalized, deduplicated feed of rental listings β Kijiji and RentFaster.ca for Canada, OpenRent for the UK, Zumper for the US β with optional nearest-amenity distances (transit, grocery, school, β¦) attached to every listing.
Most rental scrapers give you one site in that site's own ad-hoc shape. This Actor gives you every source in a single schema across countries, collapses the same unit posted to multiple sites into one row, and can tell you how far each place is from the subway β a signal no other rental scraper on Apify ships.
Why this is different
| Typical single-site scraper | This Actor | |
|---|---|---|
| Sources | One | Kijiji + RentFaster (CA), OpenRent (UK), Zumper (US) |
| Schema | Per-site, ad-hoc | One unified schema across sources & countries |
| Duplicates | You dedupe yourself | Cross-source dedup built in (also_on) |
| Location intelligence | Lat/lng only | Nearest-amenity distances, included free |
Input
Scope
| Field | Type | Default | Notes |
|---|---|---|---|
country | string | "CA" | CA (Kijiji + RentFaster), GB (OpenRent), or US (Zumper) |
sources | array | all for the country | Sites to scrape; other countries' sources are ignored |
cities | array | [] (all) | City names, e.g. ["Toronto","Calgary"], ["London"], ["Austin","Seattle"] |
maxPerCity | int | 100 | Cap per city, per source |
dedupe | bool | true | Merge cross-source duplicates |
Filters (all optional β applied cheapest-first)
| Field | Type | Notes |
|---|---|---|
minRent / maxRent | int | Monthly rent bounds, e.g. maxRent: 2500 |
minBedrooms / maxBedrooms | int | For exactly 2-bed, set both to 2. 0 = include bachelor |
keywords | array | Title/description must contain ALL (case-insensitive). e.g. ["female"], ["parking","balcony"] |
excludeKeywords | array | Drop if title/description contains ANY. e.g. ["no pets"] |
nearAmenities | array | Keep listings within maxAmenityDistanceM of each type: subway, train, bus_stop, grocery, cafe, pharmacy, park, school, university, library, gym, hospital. Auto-enables enrichment |
maxAmenityDistanceM | int | Default 800 (β10-min walk) |
nearAddress | string | A specific place to anchor on, e.g. "200 Bay St, Toronto". Geocoded, then listings kept within nearAddressRadiusM. Use this for "near my workplace" |
nearAddressRadiusM | int | Default 2000 |
Enrichment & infra
| Field | Type | Default | Notes |
|---|---|---|---|
enrichAmenities | bool | false | Attach amenity_distances_m even without a nearAmenities filter (fast, free) |
enrichRadiusM | int | 1500 | Amenity search radius |
maxEnrich | int | 200 | Cap on listings enriched per run |
proxyConfiguration | object | Apify Proxy on | Recommended β see below |
Examples:
// minimal{ "sources": ["kijiji", "rentfaster"], "cities": ["Toronto"], "maxPerCity": 50 }// "2-bed under $2500 in Toronto, near a subway, female-only"{"cities": ["Toronto"], "minBedrooms": 2, "maxBedrooms": 2,"maxRent": 2500, "nearAmenities": ["subway"], "maxAmenityDistanceM": 800,"keywords": ["female"]}// "1-bed within 2 km of my office at 200 Bay St"{ "cities": ["Toronto"], "maxBedrooms": 1, "nearAddress": "200 Bay St, Toronto", "nearAddressRadiusM": 2000 }
"Near X" β two different mechanisms
- Near a type of place (subway, grocery, universityβ¦) β
nearAmenities. Backed by OpenStreetMap; great coverage in Canadian cities. - Near a specific place (your office, a named landmark) β
nearAddress. Geocoded to one point. Amenity categories can't find a specific employer (OSM may not have "Company X"), so usenearAddressfor that.
Description questions (e.g. "female only", "no pets")
The full description is always in the output. For literal phrases, use keywords / excludeKeywords (deterministic, server-side). For nuanced interpretation, let an LLM read the returned descriptions β e.g. via Apify's MCP server, Claude can run this Actor and reason over the results in chat. Note: keyword matching is literal, so it depends on how the lister phrased it, and gender-restricted whole-unit ads may run into provincial human-rights rules (shared/roommate situations are typically exempt) β that's on the data, not the filter.
Output
Each dataset item (empty fields omitted):
{"source": "kijiji","also_on": ["rentfaster"],"source_id": "1700123456","url": "https://www.kijiji.ca/v-apartments-condos/...","title": "Bright 2BR near subway","address": "123 King St W, Toronto, ON","city": "Toronto","province": "ON","postal_code": "M5V 1J5","lat": 43.6453,"lng": -79.3806,"country": "CA","monthly_rent": 2450,"currency": "CAD","bedrooms": 2.0,"bathrooms": 1.0,"sqft": 720,"property_type": "apartment","furnished": false,"pet_friendly": true,"utilities_included": ["heat", "water"],"available_from": "2026-07-01","description": "β¦","amenity_distances_m": { "subway": 320, "grocery": 150, "park": 410 },"scraped_at": "2026-06-27T12:00:00+00:00"}
bedrooms: 0.5 means bachelor/studio. also_on lists other sites the same
unit was found on (only when dedupe is enabled). monthly_rent is always a
per-calendar-month figure in currency (CAD or GBP) β weekly UK quotes are
normalized for you.
UK specifics (country: "GB", OpenRent): province holds the nation code
(ENG/SCT/WLS/NIR), postal_code is the outward code only ("WC2N" β
UK listings don't publish full postcodes before enquiry), and description is
the search snippet, not the full ad text.
US specifics (country: "US", Zumper): province holds the state code,
apartment complexes yield one row per advertised floorplan (same address,
distinct source_id), monthly_rent is that floorplan's "from" price, and
description is a short summary.
Use it from Claude (MCP) π€
This Actor is built to be driven by an AI agent, not just a form. Connect Apify's MCP server to Claude (Desktop, Claude Code, or any MCP client) and Claude can run it from a plain-English request, then reason over the results β no code.
- Add the hosted MCP server
https://mcp.apify.com(OAuth), or run@apify/actors-mcp-serverlocally with yourAPIFY_TOKEN. - In Claude, just ask:
"Run the Canada rentals actor for Toronto β 2-bed under $2500 near a subway β and recommend the best 3."
Claude maps that straight onto the inputs β
{cities:["Toronto"], minBedrooms:2, maxBedrooms:2, maxRent:2500, nearAmenities:["subway"]} β
runs the Actor, reads the dataset, and answers in chat. Because the filters
(maxRent, minBedrooms, keywords, nearAmenities, nearAddress) are
pushed into the Actor, Claude isn't post-filtering a huge blob β it gets a
short, correct set back. The amenity_distances_m field is what lets it answer
"near a subway / grocery / school" precisely instead of guessing from text.
Proxy β please read
- RentFaster.ca, OpenRent, and Zumper sit behind bot challenges that
fingerprint the TLS handshake, so browser-like headers alone get blocked.
The Actor forges a real Chrome TLS/HTTP2 fingerprint (via
curl_cffi) on a sticky IP to clear them; a residential proxy is still recommended for a clean IP. - Kijiji rate-limits and blocks datacenter IPs aggressively.
Use Apify Proxy (residential group) for production runs, and set
apifyProxyCountry to match your country input (CA, GB, or US). The
default input already enables Apify Proxy.
Amenity enrichment
Nearest-amenity distances come from bundled offline POI indexes β ~225k Canadian, ~529k UK, and ~1.14M US POIs (OpenStreetMap, via Geofabrik) shipped inside the Actor and queried in-process. No external API, no rate limits: enriching hundreds of listings takes well under a second, and it's included free (no per-listing enrichment charge). Stations, groceries, cafes, pharmacies, schools, universities, libraries, gyms and hospitals carry their OSM name too β the map labels them "Charing Cross β subway Β· 240m", not just a dot. The snapshots are refreshed periodically; POIs are static infrastructure so they don't need to be live.
Legal & fair use
Scrapes only publicly visible listing data β no logins, no private data. You are responsible for your use of the output. Kijiji and RentFaster each have Terms of Use that restrict automated access; review them and your jurisdiction's rules, run politely (low concurrency, sensible caps), and don't redistribute in ways those terms prohibit. This Actor is provided for research and personal use.
Roadmap
- Australia. Every major AU portal (Domain, realestate.com.au, Gumtree AU, Flatmates, rent.com.au) hard-blocks automation today; support waits on a headless-browser approach being worth it.
- More UK/US sources for cross-source dedup (OpenRent and Zumper are single-source per country today).
- Facebook Marketplace + rentals.ca sources (best-effort; both are anti-bot).
- Listing-level change tracking (price drops, relistings).
Development
This repo is the Actor: src/ is the code that runs on Apify
(python -m src), .actor/ holds the actor/input/dataset schemas, and the
Dockerfile builds the image. src/data/pois_<cc>.npz are the bundled offline
POI indexes, one per country (rebuild from Geofabrik extracts with
tools/build_poi_index.py --country CA β needs pip install osmium β then
push). Adding a source or country starts at the registry in
src/sources/__init__.py.
python3.12 -m venv .venv.venv/bin/pip install -r requirements.txt.venv/bin/python test_smoke.py # offline: parsing, dedup, filters (also runs in CI).venv/bin/python live_check.py # hits the real sites, no Apify SDK needed.venv/bin/python harness_e2e.py # full pipeline against live sites, Apify calls stubbedapify push # deploy (manual β no CI deploy)
Local live_check/harness_e2e runs may see Kijiji 403s from home/datacenter
IPs β that means "use a residential proxy", not "the code is broken"; the real
Kijiji test is a cloud run with Apify Proxy (residential group).
Before touching scrapers or dependency pins, read docs/PROJECT_NOTES.md β it records which sites are viable, the exact Cloudflare workarounds, and the load-bearing version pins.