Apartments.com Scraper & Floor Plan Units avatar

Apartments.com Scraper & Floor Plan Units

Under maintenance

Pricing

from $2.99 / 1,000 results

Go to Apify Store
Apartments.com Scraper & Floor Plan Units

Apartments.com Scraper & Floor Plan Units

Under maintenance

🏒 Apartments.com Scraper (apartments-com-scraper) pulls apartment listings, prices, amenities, and availability from Apartments.com fast. πŸš€ Perfect for real estate research, lead gen & market analysisβ€”organized, export-ready data. βœ…

Pricing

from $2.99 / 1,000 results

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Apartments.com Scraper β€” Units, Floor Plans and Rent Data

Apartments.com Scraper & Floor Plan Units turns any Apartments.com property page, city page or search URL into three linked row types: the property record (address, coordinates, rating, rent band, unit-rent dispersion), every individually-listed unit (unit number, exact rent, beds, baths, sqft, price per sqft, move-in date, application link), and every floor-plan model (plan name, sqft range, rent band, pricing model, plan image). Property managers, investors and market analysts use it to price and track live inventory at the unit level instead of the advertised "Studio–2 Beds, $2,910–$5,695" range. Rows stream into the dataset live as each property finishes.

⚠️ Apartments.com caps every search at 28 pages

This is Apartments.com's own ceiling, not this Actor's, and it is worth knowing before you rely on a search URL to enumerate a whole market. A city or neighbourhood search page serves at most 28 result pages at roughly 40 properties per page β€” call it up to ~1,120 properties per search. The lastSearchPage input controls where a run stops within that ceiling: set it to a specific page to stop early, or leave it at 0 to crawl until Apartments.com itself runs out of results, which is never more than page 28. No input value raises this past what Apartments.com serves.

What is Apartments.com Scraper & Floor Plan Units?

Apartments.com Scraper & Floor Plan Units is an Apify Actor that reads Apartments.com property pages β€” the live embedded ApartmentComplex ld+json block and the on-page unit and floor-plan markup β€” and returns one property row plus one child row per unit and per floor-plan model, linked by parentId. Output is typed JSON with a stable schema, whether you point it at one listing or a whole city.

No Apartments.com account, login or cookie is used β€” every field comes from the same page any anonymous visitor loads.

  • Discovery by direct property URL, by city/neighbourhood/map search URL, or by a plain-text location (locationSearch) that the Actor converts into a search URL itself
  • Per-unit inventory: unit number, exact rent, beds, baths, sqft, price per sqft, move-in date, and the external application-portal link
  • Per-floor-plan models: plan name, bed/bath, sqft range, rent band, pricing model and the plan image
  • Property-level rent economics rolled up from the surviving units: min/median/max/spread rent, average and median price per sqft, and the percentage of units available "Now"
  • Real filters on availability and rent band, applied per unit, plus independent row caps for properties, units and floor plans
  • Optional photo gallery and video/3D tour arrays, off by default to keep rows smaller

What Apartments.com data is publicly available to scrape?

Everything this Actor returns is visible on the public listing page without logging in. What sits behind a third party is completing an application, not reading the unit's terms.

Data categoryPublicly availableBehind something else
Property identity, address, coordinates, ratingβœ“ Publicβ€”
Advertised rent band and verified-listing badgeβœ“ Publicβ€”
Individual unit inventory (number, rent, beds/baths, sqft, move-in date)βœ“ Publicβ€”
Floor-plan models (name, sqft range, rent band, image)βœ“ Publicβ€”
Photo gallery and video/3D toursβœ“ Public (opt-in fields)β€”
Submitting an application for a specific unitLink captured (applicationUrl)Completed on the external portal (RentCafe, Yardi, etc.)
Leasing-office phone / direct contactNot returned by this ActorCovered by a leasing-office-contacts variant instead

What data can I extract with Apartments.com Scraper & Floor Plan Units?

Each run returns three structurally distinct row types, all type-tagged and linked by parentId. They are documented separately below because they are not the same shape β€” a unit row does not carry rent dispersion, and a property row does not carry a unit number.

Property fields β€” identity, location and rent economics

One row per property, type: "property", isChild: false, parentId: null.

FieldDescription
idApartments.com listing ID, taken from the URL
propertyNameProperty name
urlCanonical property page URL
breadcrumbsSite breadcrumb trail (Home β†’ state β†’ city β†’ property)
lastUpdatedPage's og:updated_time, as published
lastUpdatedIsoISO-8601 lastReviewed value from the ld+json block
locationObject: fullAddress, state, city, neighborhood, postalCode, streetAddress, neighborhoodFromBreadcrumb
coordinatesObject: latitude, longitude
ratingListing rating, if published
isVerifiedWhether the page carries Apartments.com's "Verified Listing" badge
rentObject: min, max β€” the property's own advertised rent band
transportationArray of nearby transit stops: name, url, drive, distance
neighborhoodReal neighbourhood name, read from ld+json mentions
typeAlways "property"
isChildAlways false
parentIdAlways null
unitNumberAlways null β€” present so the field lines up across all three row types in a single table
floorPlanCountTotal floor-plan models found on the page, before maxFloorPlansPerProperty truncates the child rows
unitCountNumber of units that survived availabilityFilter / minUnitRent / maxUnitRent
unitRentMin / unitRentMax / unitRentMedian / unitRentSpreadRent dispersion computed from the surviving units, not the advertised band
unitSqftMin / unitSqftMaxSqft range across the surviving units
avgPricePerSqft / medianPricePerSqftPrice-per-sqft computed from the surviving units
unitsAvailableNowCount of surviving units marked "Now"
availableNowPctunitsAvailableNow as a percentage of units that carry any availability flag
bedroomMixObject counting surviving units per bedroom label (studio, 1br, 2br, 3plus)
imagesFull photo-gallery URL array β€” only present when includeAllImages is true
virtualToursVideo and 3D tour objects β€” only present when includeVirtualTours is true
scrapedAtUTC ISO timestamp for the row

images and virtualTours are omitted from the row entirely when their toggle is off, rather than written as empty arrays β€” so a row's key set tells you which options were on for that run.

Unit fields β€” the per-unit inventory

One row per individually-listed unit, type: "unit", isChild: true, parsed from li.unitContainer.

FieldDescription
id{parentId}-{unitKey or unitNumber}
typeAlways "unit"
isChildAlways true
parentIdThe owning property's id
propertyNameOwning property's name
urlOwning property's page URL
unitNumberUnit number as published
rentExact rent for this unit
bedsBedroom count
bathsBathroom count
sqftUnit square footage
pricePerSqftrent / sqft, rounded to 2 decimals
availableDateMove-in date exactly as published (e.g. "Aug 5", "Now")
availableDateIsoMove-in date resolved to ISO YYYY-MM-DD; null for "Now" rather than a fabricated date
availableNowtrue when the published date starts with "Now"
floorPlanNameName of the floor-plan model this unit belongs to
unitKeyApartments.com's internal unit key
modelKeyApartments.com's internal floor-plan-model key β€” the join key back to the floor-plan row
applicationUrlDecoded external application-portal link, or null
applicationVendorHostname of applicationUrl (e.g. apply.rentcafe.com), or null
locationThe owning property's full location object
scrapedAtUTC ISO timestamp for the row

Apartments.com renders the same unit once per bedroom tab on the page; units are de-duplicated on unitKey before rows are built, so each real unit appears once.

Floor-plan fields β€” the per-model rollups

One row per floor-plan model, type: "floorPlan", isChild: true, parsed from div.priceGridModelWrapper.

FieldDescription
id{parentId}-plan-{modelKey or floorPlanName}
typeAlways "floorPlan"
isChildAlways true
parentIdThe owning property's id
propertyNameOwning property's name
urlOwning property's page URL
floorPlanNamePlan name
modelKeyApartments.com's internal model key
beds / bathsBed/bath count for the plan
sqftMin / sqftMaxPlan's sqft range
planRentMin / planRentMaxPlan's rent band as published
pricingModel"Total Monthly Price" or "Plus Fees", read from the plan's own rent label; null when neither phrase is present
planImageUrlPlan image URL, read from the on-page .floorPlanButtonImage element; null β€” not a placeholder β€” when the plan has no published image
availableUnitCountCount of surviving unit rows (post-filter) tied to this modelKey
locationThe owning property's full location object
scrapedAtUTC ISO timestamp for the row

Floor plans are rendered once per bedroom tab as well and are de-duplicated on modelKey before rows are built.

Error rows

A fourth, uncharged row type covers everything that isn't data: type: "error", with id: null, isChild: false, parentId: null, url, propertyName: null, errorReason (e.g. akamai_challenge, http_404, parse_failed, engine_exhausted, no_properties_discovered) and scrapedAt. See Pay-per-event under Output for how to filter these out.

Why not build this yourself?

Apartments.com (CoStar Group) does not publish a self-serve developer API for listing or unit-level data, so the alternative is scraping the site directly β€” and Apartments.com runs Akamai Bot Manager in front of it, which is where a DIY build spends most of its time.

Measured live: a plain HTTP client (curl_cffi or any static requester) gets back an HTTP 200 that is actually a 2,490-byte Akamai JS interstitial β€” a passing status code carrying no data. Headless Chromium is hard-403'd on every attempt, proxied or not; its TLS fingerprint is denied outright. Playwright Firefox through an Apify US residential proxy is the combination that returned real pages on first try and then served 8 consecutive listings on one sticky exit IP with zero re-rolls (measured 2026-07-18). Even the browser's User-Agent matters here: forcing a Windows UA from this Actor's Linux container earned an instant 338-byte "Access Denied" page on every exit IP tested, while the browser's own OS-consistent UA passed β€” Akamai fingerprints the TCP/TLS stack alongside the header, and a mismatched one is a tell by itself.

None of that is a one-time setup cost. Akamai's challenge markers, the residential IP rotation ladder, and the browser/UA combination that currently works all drift, so a DIY scraper here is an ongoing anti-bot maintenance job, not a script you write once.

How to use Apartments.com Scraper & Floor Plan Units

Apartments.com Scraper & Floor Plan Units runs on Apify. Start it from the Apify Console or call it through the Apify API.

  1. Open the Actor on Apify and click Try for free
  2. Fill either 🏒 Property or search URLs (propertyUrls) or πŸ“ Location (locationSearch) β€” you don't need both. A direct property URL is scraped as-is; a city, neighbourhood or map URL is crawled and every property on it is scraped; a plain location string is converted into a search URL for you
  3. Set Maximum properties (maxProperties) and, if you're working a search URL, Last search page (lastSearchPage) β€” remember the 28-page ceiling above
  4. Leave Collect individual units and Collect floor-plan models on if you want the child rows (both default on); set their per-property caps
  5. Narrow with Availability filter, Minimum unit rent and Maximum unit rent if you only want a subset of units
  6. Leave Proxy configuration on Apify US Residential β€” Apartments.com challenges datacenter and direct traffic
  7. Click Start, then export the dataset as JSON, CSV or Excel, or read it through the Apify API

If both propertyUrls and locationSearch are left empty, the run logs "nothing to do" and exits without pushing any rows.

How maxProperties, maxUnitsPerProperty and maxFloorPlansPerProperty interact

maxProperties caps property rows only. Unit and floor-plan rows are additional and are capped per property by maxUnitsPerProperty and maxFloorPlansPerProperty β€” the totals multiply. maxProperties=5 with maxUnitsPerProperty=20 produces up to 5 property rows and up to 100 unit rows in the same run; add maxFloorPlansPerProperty=20 and you can get up to 100 floor-plan rows on top of that, if that many models actually exist. Set either per-property cap to 0 for unlimited β€” large communities really do list 79+ distinct units, so leave a cap on unless you specifically want everything.

What can you do with Apartments.com unit and floor-plan data?

  • 🏒 A property manager or leasing team benchmarking against nearby competitors pulls a market's properties with maxProperties set high and reads unitRentMedian, avgPricePerSqft and availableNowPct per property to see where their own units sit relative to the market.
  • πŸ’° An investor or market analyst screening a submarket sets availabilityFilter: "now" with minUnitRent/maxUnitRent to isolate move-in-ready inventory in a price band, then joins unit rows back to their property row on parentId to compare rent-per-sqft across buildings.
  • πŸ“Š A real estate research team tracking a neighbourhood over time re-runs the same propertyUrls weekly and diffs unitCount, unitRentMin/Max and bedroomMix per property to catch inventory and pricing shifts before they show up in aggregate reports.
  • πŸ€– An AI engineer building a rental-search assistant indexes propertyName, location, floorPlanName and rent into a vector store so an agent can answer "which 2-bed units under $3,200 are available now in Brookline" against live per-unit data instead of a stale advertised range.

How does Apartments.com Scraper & Floor Plan Units handle rate limits and blocking?

The Actor drives a real headless Firefox browser (not Chromium) through a sticky Apify US Residential exit IP, reused for the whole run and rolled only when a page is actually challenged. Each run opens with a homepage warm-up so the exit IP earns its Akamai cookies on a cheap page before the first real target, and image/media/font requests are blocked at the network layer β€” none of the data this Actor parses comes from a binary asset.

A response is treated as blocked when its body is under 6,000 bytes or carries an Akamai interstitial marker in its first 8,000 characters. Rather than a fixed wait, the Actor polls for the page's real content marker up to 20 times, reloading at two points in that sequence, because the Akamai challenge posts its sensor payload and then reloads itself. Search-results pages are additionally "settled" by re-reading while the listing-card count is still growing, so a soft partial page doesn't silently under-count. A 404 or 410 is treated as a dead link, not a block, and is not retried. A page that still won't clear after up to 6 IP rolls is given up on and logged with a reason; after 3 consecutive fully-failed property pages, the Actor marks itself exhausted and pushes the remaining queued URLs as uncharged error rows rather than hanging or silently truncating the run.

⬇️ Input

None of the 15 parameters are required by the schema β€” propertyUrls and locationSearch are the two ways to give the Actor something to scan, and at least one of them needs a value or the run has nothing to do.

ParameterRequiredTypeDescriptionExample Value
propertyUrlsNoarrayApartments.com URLs in bulk. Property pages are scraped directly; city/neighbourhood/map URLs are crawled and every property on them is scraped. Either fill this or locationSearch.["https://www.apartments.com/brookline-ma/"]
locationSearchNostringFree-text location instead of a URL β€” city, neighbourhood or ZIP. Converted into an Apartments.com search URL and crawled like any other start URL."Brookline MA"
maxPropertiesNointegerCaps PROPERTY rows only. Unit and floor-plan rows are capped separately. 0 = unlimited. Minimum 0, maximum 10000, default 5.5
lastSearchPageNointegerStop paginating a search URL after this page (40 properties per page). 0 = crawl until Apartments.com runs out of results β€” at most 28 pages. Minimum 0, maximum 28, default 0.0
includeUnitsNobooleanEmit one child row per individually-listed unit. Default true.true
maxUnitsPerPropertyNointegerCaps unit child rows per property. 0 = unlimited. Minimum 0, maximum 500, default 25.25
includeFloorPlansNobooleanEmit one child row per floor-plan model. Default true.true
maxFloorPlansPerPropertyNointegerCaps floor-plan child rows per property. 0 = unlimited. Minimum 0, maximum 500, default 25.25
availabilityFilterNostring (enum)Which units to keep: "any", "now" (available now only) or "future" (future move-in only). Default "any"."any"
minUnitRentNointegerDrop units renting below this amount, applied to the exact per-unit rent. 0 = no minimum. Minimum 0, maximum 100000, default 0.0
maxUnitRentNointegerDrop units renting above this amount. 0 = no maximum. Minimum 0, maximum 100000, default 0.0
includeAllImagesNobooleanAdd an images array of every gallery photo URL published for the property. Default false.false
includeVirtualToursNobooleanAdd a virtualTours array of video and 3D tour data. Not every property publishes tours; those return an empty array. Default false.false
requestDelayNonumberPause before each page load, plus a small random jitter. Minimum 0, maximum 30, default 1.0.1.0
proxyConfigurationNoobjectApify proxy settings. US Residential is prefilled and effectively required β€” datacenter and direct traffic is challenged. Paste custom proxy URLs to use your own residential provider instead.{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}

Example input

{
"propertyUrls": ["https://www.apartments.com/brookline-ma/"],
"maxProperties": 5,
"lastSearchPage": 0,
"includeUnits": true,
"maxUnitsPerProperty": 25,
"includeFloorPlans": true,
"maxFloorPlansPerProperty": 25,
"availabilityFilter": "any",
"minUnitRent": 0,
"maxUnitRent": 0,
"includeAllImages": false,
"includeVirtualTours": false,
"requestDelay": 1.0,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Common pitfall: propertyUrls and locationSearch are each individually optional, but they answer the same question β€” where to look. Leave both empty and the run exits immediately with nothing pushed; the schema won't stop you from submitting an empty input, but the Actor will.

⬆️ Output

Every row is typed JSON tagged with type (property, unit, floorPlan, or error), all sharing one dataset so a single export gives you the full property-and-inventory tree, joined on id / parentId. Export as JSON, CSV or Excel, or read the dataset through the Apify API. The Actor's own dataset also ships four preset views β€” a combined table plus one narrowed to unit columns, one to floor-plan columns, and one to property/rent-economics columns.

Pay-per-event

Property, unit and floor-plan rows are pushed under the row_result charged event β€” that's what you pay for. Error/accounting rows (type: "error", covering a challenged page, a 404, a parse failure, an exhausted engine, or no properties discovered) are pushed to the same dataset without a charged event, so they cost nothing. Filter them out of downstream processing with item["type"] != "error".

Example output β€” property row

{
"id": "wqc416h",
"propertyName": "Forte at 1440 Beacon",
"url": "https://www.apartments.com/forte-at-1440-beacon-brookline-ma/wqc416h",
"breadcrumbs": ["Home", "Massachusetts", "Brookline", "Forte at 1440 Beacon"],
"lastUpdated": "2026-07-20T00:00:00Z",
"lastUpdatedIso": "2026-07-20T00:00:00.000Z",
"location": {
"fullAddress": "1440 Beacon St, Brookline, MA 02446",
"state": "Massachusetts",
"city": "Brookline",
"neighborhood": "Washington Square",
"postalCode": "02446",
"streetAddress": "1440 Beacon St",
"neighborhoodFromBreadcrumb": "Brookline"
},
"coordinates": { "latitude": 42.3372, "longitude": -71.1256 },
"rating": 4.2,
"isVerified": true,
"rent": { "min": 2400, "max": 4900 },
"transportation": [
{ "name": "Washington Square", "url": "https://www.apartments.com/transit/ma/brookline/washington-square/abc1234/", "drive": "3 min", "distance": "0.8 mi" }
],
"neighborhood": "Washington Square",
"type": "property",
"isChild": false,
"parentId": null,
"unitNumber": null,
"floorPlanCount": 6,
"unitCount": 18,
"unitRentMin": 2400,
"unitRentMax": 4900,
"unitRentMedian": 3150.0,
"unitRentSpread": 2500,
"unitSqftMin": 550,
"unitSqftMax": 1180,
"avgPricePerSqft": 3.21,
"medianPricePerSqft": 3.05,
"unitsAvailableNow": 7,
"availableNowPct": 38.9,
"bedroomMix": { "studio": 3, "1br": 8, "2br": 5, "3plus": 2 },
"scrapedAt": "2026-07-25T14:02:11+00:00"
}

Example output β€” unit row

{
"id": "wqc416h-u204",
"type": "unit",
"isChild": true,
"parentId": "wqc416h",
"propertyName": "Forte at 1440 Beacon",
"url": "https://www.apartments.com/forte-at-1440-beacon-brookline-ma/wqc416h",
"unitNumber": "204",
"rent": 2950,
"beds": 1,
"baths": 1.0,
"sqft": 720,
"pricePerSqft": 4.1,
"availableDate": "Aug 5",
"availableDateIso": "2026-08-05",
"availableNow": false,
"floorPlanName": "1 Bed 1 Bath A",
"unitKey": "u204",
"modelKey": "m1b1baA",
"applicationUrl": "https://apply.rentcafe.com/onlineleasing/forte-at-1440-beacon/apply.aspx?listingId=204",
"applicationVendor": "apply.rentcafe.com",
"location": {
"fullAddress": "1440 Beacon St, Brookline, MA 02446",
"state": "Massachusetts",
"city": "Brookline",
"neighborhood": "Washington Square",
"postalCode": "02446",
"streetAddress": "1440 Beacon St",
"neighborhoodFromBreadcrumb": "Brookline"
},
"scrapedAt": "2026-07-25T14:02:12+00:00"
}

Example output β€” floor-plan row

{
"id": "wqc416h-plan-m1b1baA",
"type": "floorPlan",
"isChild": true,
"parentId": "wqc416h",
"propertyName": "Forte at 1440 Beacon",
"url": "https://www.apartments.com/forte-at-1440-beacon-brookline-ma/wqc416h",
"floorPlanName": "1 Bed 1 Bath A",
"modelKey": "m1b1baA",
"beds": 1,
"baths": 1.0,
"sqftMin": 700,
"sqftMax": 740,
"planRentMin": 2800,
"planRentMax": 3100,
"pricingModel": "Total Monthly Price",
"planImageUrl": "https://images1.apartments.com/floorplans/m1b1baA-forte-at-1440-beacon.jpg",
"availableUnitCount": 3,
"location": {
"fullAddress": "1440 Beacon St, Brookline, MA 02446",
"state": "Massachusetts",
"city": "Brookline",
"neighborhood": "Washington Square",
"postalCode": "02446",
"streetAddress": "1440 Beacon St",
"neighborhoodFromBreadcrumb": "Brookline"
},
"scrapedAt": "2026-07-25T14:02:12+00:00"
}

How do you filter and target specific units and floor plans?

Start with discovery: propertyUrls handles both direct property links and city/neighbourhood/map search URLs, while locationSearch is a shortcut that builds a search URL from plain text β€” use whichever you already have, but you only need one. For a search URL, lastSearchPage sets scope precision within Apartments.com's own 28-page ceiling, and maxProperties caps how many property rows you actually keep, independent of how many pages were crawled to find them.

Quality thresholds live at the unit level: availabilityFilter keeps only units marked "Now", only units with a future move-in date, or all of them, and minUnitRent/maxUnitRent drop units outside a rent band applied to the exact per-unit rent β€” not the property's advertised range. These three filters apply to unit rows only; floor-plan rows are parsed independently and are unaffected by them, so a plan with zero surviving units still returns its own row with availableUnitCount: 0.

Volume controls are the per-property caps maxUnitsPerProperty and maxFloorPlansPerProperty (each 0–500, 0 = unlimited), which multiply against maxProperties rather than stacking with it.

Three real targeting patterns:

{ "propertyUrls": ["https://www.apartments.com/brookline-ma/"], "maxProperties": 10, "lastSearchPage": 3 }
{ "locationSearch": "Miami Beach FL", "availabilityFilter": "now", "minUnitRent": 1800, "maxUnitRent": 3000 }
{ "propertyUrls": ["https://www.apartments.com/forte-at-1440-beacon-brookline-ma/wqc416h/"], "maxUnitsPerProperty": 0, "maxFloorPlansPerProperty": 0 }

The first narrows a city search to 10 properties within the first 3 result pages. The second pulls only move-in-ready units in a specific rent band across a whole metro. The third pulls the complete unit and floor-plan inventory of one named property, uncapped.

πŸ”— Want to try other SimpleAPI directory scrapers?

Scraper NameWhat it extracts
Realtor.com Agents + Recent Sold ListingsRealtor.com agent profiles by ZIP with price band, active-listing summary and recent-sold listing previews
Booking.com Scraper With Property Contact LeadsBooking.com hotels and properties shaped into outreach-ready contact leads β€” email, phone, website
Amazon Brand Research ScraperAmazon keyword-market seller mapping with brand-level share roll-ups and seller-profile enrichment

How to extract Apartments.com data programmatically

Apartments.com Scraper & Floor Plan Units is a standard Apify Actor: one API call, your Apify token as the header, structured JSON back.

Python example

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/apartments-com-scraper-floor-plan-units").call(run_input={
"locationSearch": "Miami Beach FL",
"availabilityFilter": "now",
"minUnitRent": 1800,
"maxUnitRent": 3000,
"maxProperties": 20,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["type"] == "unit":
print(item["propertyName"], item["unitNumber"], item["rent"], item["availableDateIso"])

Works in Go, Ruby, Node.js, cURL β€” any language that can make an HTTP request. Branch on type to route property, unit and floor-plan rows to the right handler.

Export to spreadsheets or CRM

Export the dataset as CSV directly from the Apify Console or the API, and the nested location, rent, coordinates and bedroomMix objects flatten into dotted columns (location.city, rent.min, and so on) that import cleanly into Google Sheets, Airtable or a CRM's custom-object import. Filter to type = unit first if you only want the per-unit rent sheet.

Scraping publicly accessible listing data is broadly permitted where no authentication is bypassed, and this Actor reads only what an anonymous visitor already sees on the public property page β€” no account, cookie or login is used.

Property records, unit inventory, floor-plan pricing and application-portal links are business and product data, not personal data β€” there is no individual tenant, renter or resident information in the output, so the personal-data regimes that govern profile or contact scraping do not attach to this output the way they would to a lead-generation tool. What does apply is contractual and database-related: Apartments.com's terms of service, and database or unfair-competition rules covering systematic reuse of a compiled catalogue.

Consult legal counsel for commercial applications involving bulk storage or republication of extracted listings.

❓ FAQ

What happens when a property has zero units currently listed as available?

The property row is still pushed. unitCount reflects however many units survived your availabilityFilter/rent filters β€” it can be 0 β€” and unitsAvailableNow / availableNowPct come back null rather than 0 when no unit on the page carries any availability flag at all, so an empty inventory is distinguishable from a fully-occupied one with unknown availability.

Can I get floor-plan models along with unit rows in the same run?

Yes. includeUnits and includeFloorPlans are independent toggles (both default true), each with its own per-property cap, so one run returns unit rows and floor-plan rows for the same property, linked back to it by parentId.

What if a property lists floor plans but has no individually bookable units?

That is a real and distinct case. Unit rows come from li.unitContainer and floor-plan rows come from div.priceGridModelWrapper β€” two independent parts of the page β€” so a property that advertises models without a currently posted unit list still returns its floor-plan rows, each with availableUnitCount: 0, while no unit rows are emitted for it.

How accurate is the rent and availability data?

It is exactly what Apartments.com's own listing page shows at request time β€” exact per-unit rent, beds, baths, sqft and move-in date are read from the same markup a site visitor sees, not estimated or inferred. Accuracy after that depends on how promptly the property manager keeps their own page current; re-run the Actor periodically if you need the freshest snapshot.

How many rows can I get per run?

maxProperties caps property rows (0–10,000; 0 = unlimited, bounded in practice by lastSearchPage's 28-page ceiling). Each property additionally contributes up to maxUnitsPerProperty unit rows and up to maxFloorPlansPerProperty floor-plan rows (each 0–500; 0 = unlimited). The caps multiply: maxProperties=5 with maxUnitsPerProperty=20 can produce up to 5 property rows and up to 100 unit rows in one run.

How do I pull only units in a specific rent band that are available right now?

Set availabilityFilter: "now" plus minUnitRent and maxUnitRent. All three apply to the exact per-unit rent and the unit's own availability flag β€” not the property's advertised band β€” and all three apply to unit rows only; floor-plan rows are unaffected.

Does Apartments.com Scraper & Floor Plan Units work with Claude, ChatGPT and other AI agent frameworks?

Yes. It is callable as a standard HTTP endpoint through the Apify API, so any agent framework that can make a request β€” LangChain, CrewAI, n8n, a custom tool definition β€” can invoke it and receive typed JSON directly.

How does Apartments.com Scraper & Floor Plan Units compare to other Apartments.com scrapers?

Checked on the Apify Store on 2026-07-25: epctex/apartments-scraper's own README states the Actor is "no longer working" due to new Apartments.com security protections and points users to a separate product instead. arlusm/apartments-scraper's own README documents a flat, nine-field output (id, title, address, pricing, beds, amenities, phone, url, imageUrl) with no per-unit or per-floor-plan rows at all. calm_necessity/ai-floor-planner is a different category of product entirely β€” a text-to-image AI floor-plan generator that turns a written prompt into a generated image, not an Apartments.com data extractor. Against that field, this Actor's difference is the three-row structure itself: real per-unit rent and availability plus real per-floor-plan pricing, both linked back to the property.

Can I use this Actor without an Apartments.com account or developer API key?

Yes. No Apartments.com login, cookie or API key of any kind is used or required β€” Apartments.com does not publish one for this data. The only credential you need is your own Apify account.

Conclusion

Apartments.com Scraper & Floor Plan Units returns the property, the individual units and the floor-plan models as three linked, typed row types β€” not a single flattened record with an advertised rent range standing in for what's actually available. Property managers, investors, market analysts and AI pipelines get exact per-unit rent, real availability, and floor-plan pricing, filterable by availability and rent band, capped independently per row type. Start a run from the Apify Console or call it through the Apify API to get the first dataset rows in minutes.

πŸ’¬ Your feedback

Found a bug, or need a field that's on the Apartments.com page but not yet in the output? Open an issue on the Actor's Issues tab. Reports that include the exact property URL are the fastest to reproduce and fix.