US Rental Listings & Real Estate Data API: Apartments, Houses avatar

US Rental Listings & Real Estate Data API: Apartments, Houses

Pricing

from $1.80 / 1,000 results

Go to Apify Store
US Rental Listings & Real Estate Data API: Apartments, Houses

US Rental Listings & Real Estate Data API: Apartments, Houses

Real estate data API for US rentals: 950,000+ property listings (apartments, houses, rooms for rent) verified in the last 30 days, with photos, rent and coordinates. Search by ZIP, city or map, get rental data and rent comps, a weekly listings feed of new and removed rentals. For apps and AI agents.

Pricing

from $1.80 / 1,000 results

Rating

5.0

(2)

Developer

HousingFeed

HousingFeed

Maintained by Community

Actor stats

1

Bookmarked

59

Total users

17

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

US Rental Listings & Real Estate Data API: apartments and houses for rent by ZIP, city or map area

Query 950,000+ US rental listings verified at the source in the last 30 days (count as of 18 October 2026) and get clean JSON back in seconds: real estate data for apartments, houses, townhomes and rooms for rent, with photos, rent, bedrooms, square feet and coordinates. Nothing is scraped while you wait: this Actor reads the HousingFeed rental database, which re-reads every source each week and removes listings that are gone.

Built for:

  • Rent comps and market research. Asking rents, bedrooms, square feet, rent_per_sqft and days_listed for any ZIP, city, state or map box.
  • Proptech and data teams. One normalized schema with stable ids, new listings and removed listings each week, ready to sync into your own database.
  • AI agents. A small, fully described input. Ask for 10 listings in a ZIP, or ask "how many" with countOnly and pay for one result.

What makes it different from a portal scraper:

  • Inventory the portals miss. Many listings come straight from property managers' own software and websites, where small landlords and local managers post first. Filter to them with managerDirectOnly.
  • Apartments, houses, townhomes and rooms for rent, including Zumper and HotPads rooms, in one schema.
  • Freshness you can check. Every row carries first_seen_at, last_seen_at, scraped_at and days_listed. By default you only get listings verified in the last 30 days.
  • Weekly changes, not just a snapshot. timeWindow: "new_7d" returns only what is new this week; timeWindow: "removed_7d" returns what disappeared, each with removed_at.

If you use this Actor more than once, bookmark it (the bookmark on its Store page) so it is one click away, and leave a short review when it has done its job: both help other people find it.

Rental data and rent comps

Every listing carries the asking rent (rent_min, rent_max, rent_usd), bedrooms, bathrooms, square feet, rent_per_sqft, days_listed and the source link, so a ZIP, city, state or map box gives you rent comps straight from what managers are asking today. These are published asking rents, not estimates. Every run of 20 or more listings also ends with a market read of what it returned: median asking rent overall and by bedrooms (with the number of listings behind each figure), where the cheapest 10% start, how many were first listed in the last 7 days and the share with photos, in the run log and in the OUTPUT record as market_summary. For rent data by band, run countOnly once per band (one result each) and compare; for the slowest units, sort by oldest and read days_listed.

Apartments and houses for rent by city: copy-paste inputs

One input per market; change maxItems to what you need (up to 25,000 a run, so a whole city such as Los Angeles fits in one run) and add minRent, maxRent or minBeds filters as you like.

  • Houston: { "state": "TX", "city": "Houston", "maxItems": 500 }
  • Los Angeles: { "state": "CA", "city": "Los Angeles", "maxItems": 500 }
  • Dallas: { "state": "TX", "city": "Dallas", "maxItems": 500 }
  • Atlanta: { "state": "GA", "city": "Atlanta", "maxItems": 500 }
  • Denver: { "state": "CO", "city": "Denver", "maxItems": 500 }
  • Chicago: { "state": "IL", "city": "Chicago", "maxItems": 500 }
  • San Francisco Bay Area: { "state": "CA", "city": "San Francisco", "maxItems": 500 } (also "Oakland", "San Jose")
  • Austin: { "state": "TX", "city": "Austin", "maxItems": 500 }
  • Miami: { "state": "FL", "city": "Miami", "maxItems": 500 }
  • New York: { "state": "NY", "city": "New York", "maxItems": 500 } (the boroughs match by ZIP; "Brooklyn" or "Queens" work on their own)

A city search covers the whole city, not just the rows that spell the name the same way; a ZIP is exact. A county works the same way: { "state": "NJ", "city": "Hudson County" } or { "state": "CA", "city": "Orange County" } (add the state when the county name exists in more than one state). When a run finds nothing, its status message says why and what to try.

A property listings feed for your app

Pull a market once, then schedule timeWindow: "new_7d" and timeWindow: "removed_7d" weekly: you get a listings feed of what appeared and what disappeared, with stable ids (id) so your copy stays in sync without re-pulling the market. The schedule recipe is below.

Real estate data for AI agents (MCP)

The input is small and every field is described, so an agent can ask for 10 listings in a ZIP, count matches with countOnly for one result, or compare rent bands. Use the API tab's MCP option in the Console; keep maxItems small.

Run it on a schedule (the most common setup)

  1. Click Try for free, enter your area (for example "state": "NY", "city": "Brooklyn") and set Time window to New in the last 7 days.
  2. Save it as a Task, then add a Schedule: weekly, on Wednesday. Sources are re-read once a week and most new listings land Sunday to Tuesday (UTC), so a Wednesday run catches each batch.
  3. Make a second task with Removed in the last 7 days on the same schedule, and delete those ids from your copy.
  4. Read the newest results from code, in JSON, CSV, Excel or XML:
https://api.apify.com/v2/actor-tasks/<YOUR_TASK_ID>/runs/last/dataset/items?token=<YOUR_TOKEN>&status=SUCCEEDED&format=json

That is a complete weekly rental feed for your market: new listings in, removed listings out, stable ids throughout.

Whole-city pulls and a daily sync

A run returns up to 25,000 listings. For a market bigger than that, or to pull in smaller pieces, set sort to stable: the run's OUTPUT record then carries nextCursor. Run again with the same filters and cursor set to that value, and repeat until nextCursor is null. Every listing comes back exactly once across the runs, so you never pay twice for the same row (paging by rent or by date can repeat rows that share a value at the edge of a page).

from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
actor = client.actor("housingfeed/rental-listings-api")
query = {"state": "TX", "city": "Houston", "sort": "stable", "maxItems": 25000}
listings, cursor = [], None
while True:
run = actor.call(run_input=dict(query, cursor=cursor) if cursor else query)
listings += list(client.dataset(run["defaultDatasetId"]).iterate_items())
cursor = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")["value"]["nextCursor"]
if not cursor:
break

To keep that copy current every day without re-buying the whole city:

  1. Once: the full pull above. Store each listing by its id.
  2. Daily: the same area with "newSinceDays": 2 (add these) and a second run with "removedSinceDays": 2 (delete these ids). Two days of overlap absorb a late schedule; the ids are stable, so a listing you already have is simply replaced.
  3. Weekly, on Wednesday: the full pull again, to pick up rent, photo and availability changes on listings you already hold. Sources are re-read once a week, so a daily full pull returns mostly the same rows.

Example areas for the full pull: { "state": "CA", "city": "Los Angeles" }, { "state": "TX", "city": "Houston" }, { "state": "IL", "city": "Chicago" }, { "state": "NY", "city": "Brooklyn" }, each with "sort": "stable", "maxItems": 25000.

Quick start (Console, curl, Python)

Click Start with the prefilled input (California, 2+ bedrooms, $1,000 to $3,500) and open the Output tab. Or call it as an API:

curl -X POST "https://api.apify.com/v2/acts/housingfeed~rental-listings-api/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"state":"TX","city":"Austin","minBeds":2,"maxRent":2500,"maxItems":200}'
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("housingfeed/rental-listings-api").call(run_input={
"state": "TX", "city": "Austin", "minBeds": 2, "maxRent": 2500, "maxItems": 200})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["rent_usd"], item["beds"], item["address"], item["url"])

Queries worth copying

Rent bands in one market, counted (one result each). Run one call per band and compare:

{ "state": "TX", "city": "Austin", "minBeds": 2, "maxBeds": 2, "minRent": 1500, "maxRent": 1999, "countOnly": true }

returns one row: { "matched": 2145, "estimated": false, "at_least": false, "kind": "live", "query": {...} } (18 Oct 2026). The $2,000 to $2,499 band returned 1,037. When the database is too busy to count a big area exactly, at_least: true means matched is a proven minimum. A whole state or the US is counted from live counts refreshed every 6 hours (estimated: true).

Rent comps inside a map box (downtown Miami):

{ "minLat": 25.70, "maxLat": 25.86, "minLng": -80.32, "maxLng": -80.10, "maxItems": 500 }

Everything new in a ZIP this week:

{ "zip": "11211", "timeWindow": "new_7d", "maxItems": 1000 }

Listings that stayed on the market longest (slow units, likely concessions):

{ "state": "FL", "city": "Orlando", "sort": "oldest", "maxItems": 200 }

Read days_listed on each row.

Property-manager inventory only:

{ "managerDirectOnly": true, "state": "GA", "city": "Atlanta", "maxItems": 2000 }

Input

FieldTypeWhat it does
statestringTwo-letter US state code (NY, CA, TX).
citystringCity name, partial match (Austin, Brooklyn), or a county (Hudson County, Orleans Parish).
zipstringExact 5-digit ZIP code.
minRent / maxRentintegerMonthly rent range in USD.
minBeds / maxBedsintegerBedroom range; 0 = studio. Same value in both = exactly N bedrooms.
minLat maxLat minLng maxLngnumberMap box; returns listings with coordinates only.
timeWindowselectnew_7d, new_30d, removed_7d, removed_30d, or blank for all live listings.
countOnlybooleanOne row with the number of matches instead of the listings, charged as one result.
managerDirectOnlybooleanOnly listings published by property managers and owners on their own software or websites.
availableNowbooleanOnly units marked available now.
withPhotosbooleanOnly listings with at least one photo.
propertyTypeselect (multiple)apartment, house, condo, townhouse, room, in any combination. Listings whose source states no type are left out of a filtered run. Use it with a city, ZIP or map box, or with managerDirectOnly; over a whole state or the whole US on every source it is refused (too slow), and nothing is charged.
sortselectbest (default: photo and coordinates first, freshest, mixed sources), newest, oldest, cheapest, rent_desc, or stable (a fixed order for paging with cursor).
maxItemsinteger1 to 25,000 listings per run (default 25). You pay per returned listing.
cursorstringnextCursor from the previous run's OUTPUT record: the next page of the same query, no listing twice.
countryselectUS is the maintained market. Other countries are older portal snapshots.
newSinceDays / removedSinceDays / freshDaysintegerAdvanced: exact day counts for the time window and the freshness cut-off (default 30 days in the US).

Output

One row per listing. Example:

{
"id": "hf_4c1d9e2b7a03f58e61d0",
"source_type": "manager_direct",
"url": "https://zincoent.appfolio.com/listings/detail/437a6260-d25c-45f9-add2-134fc743405d",
"address": "3638 W Waco Dr, 3632A, Waco, TX 76710",
"city": "Waco", "state": "TX", "zip": "76710", "country": "US",
"lat": 31.534176, "lng": -97.163802,
"rent_min": 1015, "currency": "USD", "rent_usd": 1015,
"rent_per_sqft": 1.23, "rent_per_sqm": 13.24,
"beds": 2, "baths": 1, "sqft_min": 824, "property_type": "apartment", "available": "NOW",
"image": "https://images.cdn.appfolio.com/zincoent/images/1c3f442c-.../medium.jpg",
"first_seen_at": "2026-09-11T13:36:11+00:00",
"last_seen_at": "2026-09-11T13:36:11+00:00",
"scraped_at": "2026-09-11T13:36:11+00:00",
"days_listed": 37
}

All fields: id, source_type, listing_id, url, address, street, city, canonical_city, state, zip, country, lat, lng, rent_min, rent_max, currency, rent_usd, rent_per_sqft, rent_per_sqm, beds, baths, sqft_min, sqft_max, property_type, furnished, available, units_available, granularity, image, images, description, amenities, first_seen_at, last_seen_at, scraped_at, days_listed, neighborhood, neighborhood_group, publisher_name, publisher_company. publisher_name is who publishes the listing as the source states it (the community's own name, the management company behind the listing, or "Private landlord"); null when the source states nothing. Removed listings also carry removed_at. See the Output tab for types.

days_listed counts from the day HousingFeed first saw the listing, so a listing that was already live before that is understated.

Pricing

Pay per result: $3 per 1,000 listings on the free plan, $2.40 on Starter, $2.10 on Scale and $1.80 on Business (see the Pricing tab). A countOnly call is one result. From 1 December the price includes the display licence (see Licence): $5 per 1,000 on the free plan, $4 on Starter, $3.50 on Scale, $3 on Business; nothing else is charged. Apify's free plan includes monthly credits, so you can test with real queries before paying anything: on the free plan a run returns up to 50 listings and tells you how many matched; any paid Apify plan returns up to 25,000 per run. Every run's status message and OUTPUT record say how many listings matched and how many came back.

Licence

Until 1 December 2026: results are licensed for research, analysis and internal tools: rent comps, market studies, investment screening, alerts for your own team, and prototypes. Showing the listings to the public (a search site, an app, a newsletter, a chatbot) needs a display licence. Each listing links to its source in url; keep that link when you use a listing.

From 1 December 2026 (the price change announced on 17 November), every US listing this Actor returns is the HousingFeed feed itself and comes with the display licence, included in the result price: you may show it to the public in your product for 30 days from the run, with these conditions.

  • Credit the publisher (the manager or owner named on the listing) and link to its url; enquiries go to the source. When publisher_name is empty, the link to url is the credit.
  • Show photos from the URLs supplied; do not re-host, alter or watermark them.
  • Stop showing a listing once it appears in a removed_7d run, or 30 days after its last_seen_at, whichever comes first. A weekly schedule of new_7d and removed_7d keeps a copy in sync.
  • Take a listing down within 7 days when HousingFeed or its publisher asks.
  • No reselling, sublicensing or redistributing the listings as a dataset or API, no white-labelling to other platforms, no training of models other than those serving your own product.
  • Listings are provided as published by their source; HousingFeed does not warrant completeness, accuracy or continued availability and is not responsible for a source's content. You are responsible for your product's compliance with the laws that apply to it, including fair-housing law.
  • Granted by Iron Holding B.V. (HousingFeed), non-exclusive, non-transferable, United States listings only, revocable on breach (listings come down within 7 days). The full terms are linked from the Store page.

Rows from consumer portals (includePortals: true) and other countries are research data as before and carry no display licence.

For a whole market as a file or feed with weekly change sets, email support and an invoice, request a free sample for your market or reach out to us at hello@housingfeed.com.

FAQ

How fresh is it? Every source is re-read once a week and swept for listings that disappeared. The default 30-day window keeps anything older out; each row tells you its own age.

How is this different from a Zillow or Apartments.com scraper? A scraper reads one portal live while you wait. This is a maintained database you query in seconds, with the same schema for every source, stable ids, weekly new and removed listings, and property-manager inventory the portals do not carry. If you need one portal's live page right now, a dedicated scraper is the better tool.

Are removed listings excluded? Yes, from every result. To learn which ones went, use timeWindow: "removed_7d".

Can an AI agent use it? Yes. Use the API tab's MCP option; the input is small and every field is described. Keep maxItems small (the default is 25) and use countOnly for "how many" questions.

Do you see my searches? We log the search filters of each run (location, rent and bedroom filters, how many rows came back) so we know which markets to deepen. We do not receive your name or email; Apify's user ID is stored only as a one-way hash, used to count returning users.

Is it legal? It returns publicly listed rental data. You are responsible for how you use it; see Licence above.

Something wrong or missing? Open an issue on the Issues tab, or email hello@housingfeed.com; we read every one. If this Actor saves you time, a rating on this page helps other people find it.

Single-source Actors from HousingFeed (same database, same schema)


Powered by HousingFeed · support: hello@housingfeed.com