Apartments.com API & Scraper
The Apartments.com API turns apartments.com, the largest US rental marketplace, into clean JSON in three actions.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
search takes a place, which can be a city and state, a ZIP code, a neighbourhood, a street address, a map box, or a point and a radius, and returns the rental buildings in it: the seven-character listing id, the apartments.com URL, the property name, the street address split into street, city, state and ZIP, the marketing amenity strip, the move-in specials, the leasing-office phone, the main photo and how many photos the listing has, and whether it has a video or a 3D tour. The price comes back the way the source publishes it, which is per bed count rather than per building: floor_plans carries one entry per bed count with its label, the bed number, the rent and a price_is_from flag, because a listing that reads 1,196 dollars and a plus sign for a one-bed is telling you the cheapest one-bed, not the price of one-beds. rent_min and rent_max are derived from those plans and are marked as derived. total_units is the source's own count of available units inside the box, which is a different measure from the number of buildings on the page. property/detail returns one building by listing id or URL with its coordinates, its renter rating, the published rent and bed ranges and its neighbourhood. locations turns a typed place name into the ids, coordinates and map box that search takes, and says how many units each place currently has. What the source does not publish on this surface is not invented: there is no per-plan square footage, no unit-level availability date, no fee schedule, no full pet policy text and no review count, so those are absent rather than guessed. No Apartments.com account, no browser, one ReefAPI key and the standard { ok, data, meta, error } envelope.
What arrives on an Apartments.com row, and what the open surface never publishes
Field fill measured on 2026-09-24 over 480 rows, then re-checked on 320 rows across eight cities, counted per city rather than pooled. A sparse field here is the source being silent, and it is separated from a parse gap on purpose.
| Field | Fill | What it means |
|---|---|---|
| property_id, url, phone, image | 480 of 480 | Always present. The listing key is a stable seven-character code that survives search, detail and a second search. |
| floor_plans, beds_min, beds_max | 480 of 480 | One entry per bed count, which is how the source publishes rent. rent_min and rent_max are derived from it and carry a derived flag. |
| rent_min / rent_max | 471 of 480 | The other nine publish Call for Rent. They come back with rent_published false and their bed range intact, never a zero. |
| address, city, state | 466 of 480 | A handful of placards carry no address title at all. |
| amenities | 399 of 480 | A short marketing strip, not the full building amenity list. Some placards publish none. |
| pet_policy_summary | 366 of 480 | Derived from that same strip, and absent when the strip is. The full pet policy text is not on this surface. |
| square footage per floor plan, fee schedule, review count | 0 | Not published on the open surface. Absent rather than estimated. |
A row is a building, not a unit. total_units is the source's own count of available units inside the map box, which is a different number from the buildings returned: one measured Austin box reported 30,175 units against 40 buildings on the page.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/apartments/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"location": "Austin, TX",
"limit": 40
}
}{
"ok": true,
"meta": {
"api": "apartments",
"endpoint": "search",
"mode": "live",
"latency_ms": 7153.2,
"record_count": 0,
"bytes": 199698,
"cache_hit": false,
"stop_reason": "empty_page",
"pages_read": 1,
"charged_credits": 2,
"version": "1.0.0"
},
"data": {
"results": [],
"total_units": null,
"new_unit_count": null,
"location": {
"location_id": "0hvrl11",
"display": "Austin, TX",
"type": "city",
"type_id": 2,
"city": "Austin",
"state": "TX",
"postal_code": null,
"county": null,
"market": "Austin",
"latitude": 30.29612,
"longitude": -97.73298,
"bounding_box": {
"lower_right": {
"lat": 30.07558,
"lng": -97.52759
},
"upper_left": {
"lat": 30.51666,
"lng": -97.93836
}
},
"available_unit_count": 34986
},
"bounding_box": {
"lower_right": {
"lat": 30.07558,
"lng": -97.52759
},
"upper_left": {
"lat": 30.51666,
"lng": -97.93836
}
},
"page": 1,
"limit": 40,
"sort": "default",
"filters_applied_by": null
}
}What the Apartments.com API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Rental buildings in a place. Give a `location` ('Austin, TX', '78704', 'Downtown Chicago'), or a `bounding_box`, or `latitude`+`longitude`+`radius_miles`. Each row is a BUILDING with one entry per bed count in `floor_plans` — that is how apartments.com publishes rent, and flattening it would lose the price signal. `total_units` is the source's own count of available UNITS in the box, which is a different measure from the number of buildings returned. | Real-estate investors call search to get rental buildings in a place. | location, bounding_box, latitude, longitude, radius_miles, ... |
| property/detail | One building by its listing key or apartments.com URL: name, street address, city, state, coordinates, renter rating, the published rent range and bed range, the neighbourhood label and the main photo. The full floor-plan table, fee schedule and pet policy are NOT served on the open surface — see the API notes. | Brokerage tools call property/detail to get one building by its listing key or apartments.com URL. | property_id |
| locations | Turn a typed place name into the ids, coordinates and map box that `search` takes — and the number of units each place currently has. Cities, ZIP codes, neighbourhoods, counties and street addresses all come back, each tagged with its type. | Property dashboards call locations to turn a typed place name into the ids, coordinates and map box that `search` takes. | query, limit |
Call search from your stack
curl -X POST https://api.reefapi.com/apartments/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"location":"Austin, TX","limit":40}'import requests
r = requests.post(
"https://api.reefapi.com/apartments/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"location": "Austin, TX",
"limit": 40
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/apartments/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"location": "Austin, TX",
"limit": 40
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.apartments.search with {"location":"Austin, TX","limit":40}.Who uses this API and why
- Rent-index and market-tracking pipelines store one row per building per day from floor_plans, which gives the asking rent per bed count rather than a single blended number.
- Relocation and HR tools resolve a destination with locations and then pull the buildings inside that box with search, filtered to a budget and a bed count.
- Property managers and investors watch competing buildings in a submarket by re-running the same bounding box and diffing rent per bed count over time.
- Lead-generation tools read the leasing-office phone and the move-in specials to see which buildings in a market are discounting this month.
- Mapping and site-selection tools use the coordinates and the source's own available-unit count per place to size supply before pulling a single listing.
Questions developers ask before integrating
Is an Apartments.com result one apartment or one building?
One building. Apartments.com publishes rent per bed count for a whole property, so each row carries floor_plans with one entry per bed count, Studio, 1 Bed, 2 Beds and so on, each with its own asking rent. Flattening that to a single number would throw away the only price signal the source gives, so it is kept and rent_min and rent_max are derived from it, marked as derived.
What does the plus sign on an Apartments.com rent mean?
It is the source's own from marker and it is preserved. 1,196 with a plus on a 1 Bed means the cheapest one-bedroom in that building is 1196, not that one-bedrooms cost 1196. The flag is price_is_from, the printed string is rent_display and the number is rent_from. A building that publishes no rent at all comes back with rent_display reading Call for Rent and rent_published false, never a zero.
Can I filter by price, beds, pets or amenities?
Yes, and the response tells you who applied each one. Sorting is done by the source and echoed back. The price, bed, pet, amenity, tour and specials filters are applied to the parsed rows, and filters_applied_by reads reefapi when any of them is set, so you always know whether a number came from the source's own filtering or from ours. Measured on Austin, each of min_beds, max_rent, pets, has_3d_tour and specials_only removed rows that violated it and let zero violations through. Buildings that publish no rent are left out whenever a rent filter is set, because they cannot be confirmed to match.
How do I search a specific area rather than a whole city?
Pass bounding_box as south,west,north,east, or latitude and longitude with radius_miles, and the location lookup is skipped entirely. The locations action returns the box for any city, ZIP, neighbourhood or address and costs nothing, so you can resolve once, store the box and re-run the same area for as long as you like.
Does it return floor plan square footage, fees or the full pet policy?
No, and it says so rather than guessing. Per-plan square footage, unit-level availability dates, the fee schedule, the full pet policy text, the management company name and the review count are not published on the surface this API reads, so those are absent rather than filled with an estimate. What you do get on every building is the rent per bed count, the address, the coordinates, the amenity strip, the specials, the photos and the leasing phone.
Does paging return fresh buildings?
Yes. Pages one, two and three were compared on Austin, Chicago and Brooklyn: 40 rows each, with an overlap of 11, 0 and 0 between the first two pages and 0, 0 and 2 between the first and third, because the source re-ranks sponsored placements between requests. Rows are de-duplicated by property_id inside one call, so the same building never appears twice in one response.
What is the Apartments.com API?
Apartments.com API is a ReefAPI endpoint group for us rental buildings with the asking rent per bed count, amenities, address, photos and the leasing phone. It returns live JSON through POST requests under /apartments/v1.
Is the Apartments.com API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Apartments.com calls use the same shared credit balance as every other ReefAPI engine.
Do I need an Apartments.com login or account?
No login to Apartments.com is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Apartments.com data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Apartments.com API use?
Apartments.com actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Apartments.com from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call apartments actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Apartments.com API an Apartments.com scraper?
It is the managed alternative to a DIY Apartments.com scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same us rental buildings with the asking rent per bed count, amenities, address, photos and the leasing phone back as clean JSON.
Why does my Apartments.com scraper keep getting blocked?
Most Apartments.com scrapers break on anti-bot defenses, rate limits and IP bans that need rotating residential proxies and browser fingerprinting to clear. ReefAPI handles all of that for you — no proxies, no captchas, no maintenance — and returns live JSON. Blocked calls are free.