# Rent.com Scraper - Rentals, Prices, Floor Plans & Contacts (`abotapi/rent-com-scraper`) Actor

Extract rental listings from rent.com. Get comprehensive data including monthly rent ranges, full address with GPS, beds/baths/sqft ranges, three contact phone channels, special offers, pet policy, photos, amenities, floor plans, and per-day office hours. Apartments, houses, condos, and townhomes.

- **URL**: https://apify.com/abotapi/rent-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 5 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Rent.com Scraper: Apartment, House, Condo and Townhome Listings

Rent.com Scraper turns Rent.com into structured rental data you can pull on demand or on a schedule. Search any US city and state with a full filter builder, or paste any Rent.com search result URL for filters not exposed below, and get back price, full address, GPS, beds/baths/sqft ranges, photos, amenities, special offers, pet policy, and leasing office contact details for apartments, houses, condos and townhomes. Turn on detail-page enrichment for the full description, complete amenity list, floor plans and ratings, then export the results as JSON, CSV or Excel, pull them through the API, or pipe them into the apps you already use.

### Why This Scraper?

- **Two ways to search.** Build a search from city, state and filters, or paste any Rent.com search result URL you refined in your own browser for filters not exposed below. A single property page (`/apartment/...-lc<id>`) is also accepted.
- **Every US market.** All 50 states plus DC, and all four property types: apartments, houses, condos and townhomes.
- **40+ fields from the search results alone.** Price, full address, GPS, beds/baths/sqft ranges, photos, amenities, special offers, pet policy and leasing office phones, all without an extra request per listing.
- **Detail enrichment on demand.** Switch on detail pages for the full description, complete amenity list, individual floor plans, ratings and pet-policy details, and pay the same per-listing price either way.
- **Multi-location in one run.** Add as many city and state pairs as you want, and the run walks every result page for each of them automatically, up to your Max pages / Max listings limits.
- **Built for schedules.** Turn on incremental mode to get only what changed on a recurring run, with no run ID to paste each time.
- **Resume support.** Continue an interrupted run from where it left off, without re-saving or re-paying for listings you already collected.

### Use Cases

- **Rental market researchers:** track rent ranges, availability and special offers across neighborhoods and cities over time.
- **Property management companies:** monitor competitor pricing, amenities and rent specials in their own market.
- **Relocation and listing platforms:** enrich their own site with fresh Rent.com pricing and availability data.
- **Lead-generation and outreach teams:** collect leasing office contact numbers and property manager names by market.
- **Data teams:** build historical pricing and availability datasets for forecasting and reporting.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `id` | `"lc00012345"` |
| `url` | `"https://www.rent.com/apartment/willow-creek-apartments-austin-tx-lc00012345"` |
| `name` | `"Willow Creek Apartments"` |
| `propertyType` | `"APARTMENTS"` |
| `listingTier` | `"diamond"` |
| `verified` | `true` |
| `fullAddress` | `"482 Maple Grove Rd, Austin, TX 78701"` |
| `city` / `state` / `zip` | `"Austin"` / `"TX"` / `"78701"` |
| `latitude` / `longitude` | `30.2672` / `-97.7431` |
| `bedsLabel` | `"1-3 Beds"` |
| `bathsLabel` | `"1-2 Baths"` |
| `sqftMin` / `sqftMax` | `650` / `1150` |
| `priceLabel` | `"$1,400+"` |
| `availability` | `"TODAY"` |
| `phone` / `phoneText` | `"5125550142"` / `"(512) 555-0142"` |
| `specialOffer` / `specialOfferCategory` | `"Up to 6 Weeks Free"` / `"FreeRent"` |
| `dealTypes`, `tourUrls`, `videoUrls`, `priceDropAmounts` | Deal labels (`["4 Weeks Free"]`), virtual-tour and video links, per-floor-plan price drops (`[100]`); empty lists when the listing has none |
| `squareFeetText`, `timeZoneId`, `hasTotalCostWithFees`, `hasTotalCostWithFeesMessaging`, `contactPhone`, `unitsAvailable` | Square-footage label, time zone, total-cost-with-fees flags, the listing's own contact phone and available-unit count when rent.com publishes them (otherwise `null`) |
| `amenitiesHighlighted` | `["Pet Friendly", "Pool", "Fitness Center"]` |
| `petsCats` / `petsDogs` | `true` / `true` |
| `propertyManagement` | `"Meadowbrook Residential Management"` |
| `officeHours` | `[{ "day": "Monday", "open": "09:00 AM", "close": "06:00 PM" }]` |
| `photos` / `primaryImage` / `imageCount` | array of `{id, url, caption}` / cover photo URL / `24` (`imageCount` is always `photos.length`; sample array shortened for brevity) |
| `scrapedAt` | `"2026-01-01T00:00:00.000Z"` |

Turning on **Fetch detail pages** adds `description`, `rating`, `reviewCount`, `yearBuilt`, `fees` and `petPolicyDetails`, a fuller `amenitiesAll`, and per-unit `floorPlans`; these stay `null` or SERP-only otherwise. Dataset views: **Listings** (overview), **Detail**, **Changes** (incremental fields) and **Floor plans** (one row per floor plan). Turning on **Incremental mode** adds `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt` to every emitted record; a normal run never carries these fields at all.

### How to Use

1. Pick a **mode**: `search` (city + state + filters) or `url` (paste Rent.com search result links or single property page links).
2. Fill in the fields for that mode, and switch on **Fetch detail pages** if you need the fuller record.
3. Set **Max pages** and **Max listings** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search mode, basic:**

```json
{
  "mode": "search",
  "locations": [{ "city": "Austin", "state": "TX" }],
  "propertyType": "apartments",
  "maxPages": 3
}
```

**Search mode, with filters:**

```json
{
  "mode": "search",
  "locations": [{ "city": "Denver", "state": "CO" }],
  "propertyType": "apartments",
  "bedrooms": "2",
  "maxPrice": 1500,
  "petFriendly": true,
  "maxListings": 100
}
```

**URL mode, paste pre-filtered search links:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.rent.com/texas/austin-apartments/2-bedroom",
    "https://www.rent.com/colorado/denver-apartments/max-price-2000"
  ],
  "maxPages": 4
}
```

**Detail enrichment plus incremental monitoring:**

```json
{
  "mode": "search",
  "locations": [{ "city": "Miami", "state": "FL" }],
  "propertyType": "condos",
  "fetchDetails": true,
  "incrementalMode": true,
  "maxListings": 50
}
```

#### Supported URL shapes (URL mode)

| Shape | Example | Result |
|---|---|---|
| City search | `https://www.rent.com/california/los-angeles-apartments` | Listings, walked page by page |
| Paginated | `.../los-angeles-apartments/page-2` | Starts at that page and walks forward |
| Legacy page query | `.../los-angeles-apartments?page=3` | Same as `/page-3` (the shipped example uses page 3 so it does not duplicate the `/page-2` example) |
| Houses / condos | `.../los-angeles-houses`, `.../los-angeles-condos` | Listings of that type |
| Townhouses | `.../los-angeles-townhouses` | Townhome listings (Rent.com's path word is `townhouses`) |
| Neighborhood | `.../los-angeles-apartments/hancock-park-neighborhood` | Listings in that neighborhood |
| Bedrooms | `.../los-angeles-apartments/2-bedroom` | Listings with that bedroom count |
| Studio | `.../los-angeles-apartments/studio` | Studio listings |
| Max price band | `.../los-angeles-apartments/max-price-2000` | Listings up to that band |
| Amenity flag | `.../los-angeles-apartments/pet-friendly` | Listings with that flag |
| Near me | `https://www.rent.com/near-me/apartments` | Listings near the location rent.com infers for the request |
| Other city | `https://www.rent.com/texas/austin-apartments` | Listings for that city |
| Single property | `https://www.rent.com/apartment/cahuenga-apartments-los-angeles-ca-lc6041139` | One row with the full detail-page data |
| Room detail page | `https://www.rent.com/r/...` | Not supported, skipped with a warning |
| State page, rent-trends page | `https://www.rent.com/california` | Not supported, skipped with a warning in the run log (a state page lists cities and carries no listings; a rent-trends page shows a six-listing teaser, not a search) |

Rent.com serves only one filter segment per search page (for example `/2-bedroom` or `/pet-friendly`, never both). In search mode, when you set several filters only the first (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, then Max price) is applied and the log says which others were not. A search that rent.com answers with 404 (for example a misspelled city) is reported as an error in the log, and the run fails if every search is a 404.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/rent-com-scraper").call(run_input={
    "mode": "search",
    "locations": [{"city": "Austin", "state": "TX"}],
    "propertyType": "apartments",
})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["name"], listing["priceLabel"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/rent-com-scraper').call({
  mode: 'search',
  locations: [{ city: 'Austin', state: 'TX' }],
  propertyType: 'apartments',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Resuming an unbounded walk

For a full pull (`maxPages` empty, `maxListings: 0`), two things protect a long run:

- **`resumeFromRunId`** lets you continue in a brand new run: paste the ID of a previous run (or its dataset), and this run skips every listing `id` already saved there, appending only new listings.
- A **checkpoint** is saved automatically as the run progresses. If the run is interrupted by an Apify platform migration, or you click Resurrect on a failed run, it picks back up from where it left off in the same run, without re-saving or re-paying for listings it already collected. No input is needed for this, it is automatic.

#### Incremental and recurring updates (`incrementalMode`)

Schedule this actor to re-run the same search daily or weekly and get only what changed, with no run ID to paste each time:

- Turn on `incrementalMode`. The actor derives a state key from your search or URL and filter settings (or use `stateKey` to name it yourself).
- Every emitted listing gets `changeType` (`NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`), `changedFields`, `firstSeenAt` and `lastSeenAt`.
- `NEW`, `UPDATED` and `REAPPEARED` rows are never suppressed by default. `UNCHANGED` rows are scanned, so change detection still works, but are withheld and not billed unless `emitUnchanged` is on.
- `REAPPEARED` can only happen for a listing a prior run already marked as gone (`EXPIRED`, or an unmarked placeholder seeded from a `resumeFromRunId` baseline), and `EXPIRED` itself is only produced when `emitExpired` was on for a run that completed a full, uncapped scan of the tracked search (no page or item cap cut it short, no page was blocked, and it was not a resumed run). Until you have run with `emitExpired` on and finished such a scan at least once, no listing can ever come back marked `REAPPEARED`, because nothing has been marked gone yet.
- Turn on `emitExpired` to also see, and be billed for, previously tracked listings that are no longer found. If a run cannot prove a complete scan, expired detection is skipped for that run and the prior tracked state is kept as is, so nothing is falsely marked gone.
- **What is compared:** every listing field (rent range, beds/baths, availability, units text, special offers, deals, phone, floor plans, amenities and the rest). **What is excluded** from the comparison, yet still present in the output: `scrapedAt` and the photo fields `photos`, `primaryImage` and `imageCount` (the photo CDN list is re-ordered without any change to the rental), plus any field you list in `ignoreFieldsForChanges` (the always-ignored set is `scrapedAt`, `photos`, `primaryImage`, `imageCount`). A plain name matches that field at any depth; a dotted path such as `floorPlans.unitsAvailable` matches that exact path inside lists.
- A scan that starts from a pasted result URL on page 2 or later never covers the earlier pages, so it is never treated as a complete scan and cannot mark listings `EXPIRED`.
- This is a distinct feature from `resumeFromRunId`: resume continues one interrupted run from a pasted ID, incremental mode remembers state itself across separately scheduled runs.
- Duplicates within one run, across pages, searches or URLs, are always deduplicated and pushed once, independent of `incrementalMode`.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape, the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. If the picker is empty, you have not authorized a connector yet.
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `"search"` | `"search"` (city + state + filters) or `"url"` (paste Rent.com URLs). |
| `locations` | array | none in schema (prefill: `[{"city": "Los Angeles", "state": "CA"}]`; if omitted or empty, the actor searches Los Angeles, CA) | Search mode only. List of `{city, state}` objects; state is the 2-letter US code. |
| `propertyType` | string | `"apartments"` | `apartments`, `houses`, `condos` or `townhomes`. Determines what gets fetched in search mode; in URL mode it is only a fallback label when neither the pasted URL nor the listing data states a type. |
| `bedrooms` | string | `""` (any) | Exact bedroom count: `studio`, `1`, `2`, `3` or `4` (4+). Search mode only. |
| `maxPrice` | integer | none | Rounded down to the nearest Rent.com price band (700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 2000). Below 700, no filter is applied; 2000 or more applies the $2000 band. Search mode only. |
| `petFriendly` | boolean | `false` | Show only pet-friendly listings. Search mode only. |
| `furnished` | boolean | `false` | Show only furnished listings. Search mode only. |
| `luxury` | boolean | `false` | Show only premium or luxury listings. Search mode only. |
| `dealsOnly` | boolean | `false` | Show only listings with active rent specials. Search mode only. |
| `incomeRestricted` | boolean | `false` | Show only income-restricted (affordable housing) listings. Search mode only. |
| `urls` | array | one example of each supported URL shape (see the table below) | URL mode only. One or more Rent.com search result or property page URLs; multi-URL supported. If you switch to URL mode and leave this field untouched, the field holds one example of each supported shape; they are scraped in order until `maxListings` is reached (with the default of 20, only the first example is reached). This is a changed default: earlier versions had an empty list here, so a URL-mode run with no input now scrapes these examples instead of nothing. |
| `maxPages` | integer | none | SERP pages walked per location or URL. Leave empty to walk every result page (still bounded by `maxListings`). |
| `maxListings` | integer | `20` | Stop after this many listings across all locations. `0` means no cap. |
| `fetchDetails` | boolean | `false` | Fetch each listing's detail page for the full description, complete amenity list, individual floor plans, ratings and pet-policy details. |
| `resumeFromRunId` | string | none | A previous run ID or dataset ID to continue an unbounded walk across separate runs. |
| `incrementalMode` | boolean | `false` | Recurring monitoring: compares this run with the last committed run of the same search. See the incremental section above. |
| `stateKey` | string | none | Name a monitoring campaign so state is shared across runs deliberately, instead of the automatic search-derived key. |
| `emitUnchanged` | boolean | `false` | Also output listings that did not change since the last run, tagged `UNCHANGED`. Billed like any other row. |
| `emitExpired` | boolean | `false` | Also output previously tracked listings no longer found, tagged `EXPIRED`, only after a complete scan. Billed like any other row. |
| `ignoreFieldsForChanges` | array | none | Incremental mode only. Extra fields (dotted paths allowed) left out of change detection; they stay in the output. See the incremental section above. |
| `proxy` | object | none in schema (prefill: Apify residential, country US; the same is used if omitted) | Proxy configuration. A US-residential connection is strongly recommended. |
| `mcpConnectors` | array | none | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | none | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

> **Tip, filters not in the schema:** Rent.com's URL grammar exposes only the filters above as canonical SEO segments. For other refinements (specific amenity, neighborhood), open Rent.com in your browser, apply the filter, then copy the search result URL into URL mode. The actor scrapes it as is.

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "id": "lc00012345",
  "url": "https://www.rent.com/apartment/willow-creek-apartments-austin-tx-lc00012345",
  "name": "Willow Creek Apartments",
  "propertyType": "APARTMENTS",
  "listingTier": "diamond",
  "isLuxury": false,
  "verified": true,
  "fullAddress": "482 Maple Grove Rd, Austin, TX 78701",
  "street": "482 Maple Grove Rd",
  "city": "Austin",
  "state": "TX",
  "stateName": "Texas",
  "zip": "78701",
  "latitude": 30.2672,
  "longitude": -97.7431,
  "bedsMin": 1,
  "bedsMax": 3,
  "bedsLabel": "1-3 Beds",
  "bathsMin": 1,
  "bathsMax": 2,
  "bathsLabel": "1-2 Baths",
  "sqftMin": 650,
  "sqftMax": 1150,
  "priceMin": 1400,
  "priceMax": 2600,
  "priceLabel": "$1,400+",
  "availability": "TODAY",
  "unitsAvailableText": "4 Units Available",
  "phone": "5125550142",
  "phoneText": "(512) 555-0142",
  "phoneSem": "5125550142",
  "phoneSemText": "(512) 555-0142",
  "specialOffer": "Up to 6 Weeks Free",
  "specialOfferCategory": "FreeRent",
  "deals": ["Up to 6 Weeks Free"],
  "categoryBadges": [],
  "amenitiesHighlighted": ["Pet Friendly", "Pool", "Fitness Center"],
  "amenitiesAll": ["Pet Friendly", "Pool", "Fitness Center"],
  "petsCats": true,
  "petsDogs": true,
  "petPolicyDetails": null,
  "hasVideo": false,
  "hasVirtualTour": true,
  "hasPriceDrops": false,
  "incomeRestrictions": [],
  "propertyManagement": "Meadowbrook Residential Management",
  "cplEligible": true,
  "revenue": 6,
  "sourceId": "10000001",
  "bedCountData": [
    { "beds": 1, "pricesLow": 1400, "pricesHigh": 1700, "sqftLow": 650, "sqftHigh": 750 }
  ],
  "floorPlans": [
    { "beds": 1, "baths": 1, "availableCount": 2, "priceMin": 1400, "priceMax": 1700, "sqftMin": 650, "sqftMax": 750, "availableDate": null, "units": [] }
  ],
  "officeHours": [
    { "day": "Monday", "open": "09:00 AM", "close": "06:00 PM" }
  ],
  "leasingTerms": [],
  "description": null,
  "rating": null,
  "reviewCount": null,
  "yearBuilt": null,
  "fees": null,
  "photos": [
    { "id": "00000", "url": "https://i.rent.com/t_3x2_fixed_webp_lg/00000", "caption": null }
  ],
  "primaryImage": "https://i.rent.com/t_3x2_fixed_webp_lg/00000",
  "imageCount": 24,
  "updatedAt": "2026-01-01T00:00:00.000Z",
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

### Plan Requirement

Rent.com protects its search and detail pages with a JavaScript challenge that plain HTTP clients do not pass (it answers with an empty HTTP 202 instead of the page), so the actor needs proxy access and does not work with no action on your side. The proxy field defaults to Apify's residential proxy group with country set to US. A paid Apify plan is recommended because it includes residential proxies.

- **Paid plan (residential granted):** the default connection is used, and a backup connection is used only if it becomes unavailable. When that happens the log says: "Served over the backup connection (the default connection was unavailable)."
- **Free plan (no residential proxies):** the run continues on a backup connection and logs a warning: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." Some pages may fail to load. If none can, the run fails with: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Rent.com pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- **Proxy refused for the account:** the run fails with "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required". If you entered your own proxy URLs, check their credentials.
- **Pages fail to load on a plan that has access:** the run fails with "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later." This is never reported as an empty search.

### FAQ

#### How much does it cost?

Billing is pay per event: one run-start event per run and one result event per listing pushed to the dataset. Turning on detail-page enrichment does not add events. Listings suppressed as unchanged in incremental mode are not pushed and not billed. The **Pricing** tab shows the current rates. Use **Max listings** and **Max pages** to cap the cost of any run.

#### Is it legal to scrape Rent.com?

This actor collects only publicly available rental listing data. You are responsible for how you use it: follow Rent.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Contact details and property descriptions may be subject to third-party rights.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Unchanged listings are not billed unless you turn on **Emit unchanged**. Listings that disappear are only tagged `EXPIRED`, and can only later come back tagged `REAPPEARED`, once you have run with **Emit expired** on for a run that completed a full scan.

#### Why did my run return an empty dataset instead of failing?

If a page for a city or URL is rejected by the site, that search stops at that point (any earlier pages it already read are kept) with a warning, and the run moves on; if every search ends up blocked, the run still finishes successfully with an empty dataset and a warning telling you to check the proxy country, use your own residential proxy URLs, or try again for a fresh connection. An empty dataset can also mean every location was invalid, url mode had no URLs, or, in incremental mode, that everything found was UNCHANGED and suppressed. The run only fails outright if no working proxy connection could be established at all before any scraping started, or if `resumeFromRunId` points to a run or dataset your account cannot read, or if `resumeFromRunId` is combined with `incrementalMode` on a search that already has saved state.

#### Why do I need a proxy, and why residential US?

Rent.com answers plain requests with a JavaScript challenge, and the actor passes it through a US-residential connection. The proxy field defaults to the right setting. On a free plan the actor falls back to a backup connection and warns you (see Plan Requirement); results there can be partial.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🏠 <a href="https://apify.com/abotapi/apartments-com-scraper"><b>Apartments.com Scraper</b></a><br>Scrape Apartments.com rentals by city, ZIP, neighborhood, address or URL. Extract rent...</td><td>🏠 <a href="https://apify.com/abotapi/zumper-scraper"><b>Zumper Scraper</b></a><br>Scrape Zumper.com rental listings: apartments, houses, condos and rooms. Pulls 60+ fields...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/realtor-com-scraper"><b>Realtor.com</b></a><br>Extract property listings from realtor.com. Get comprehensive data, including prices...</td><td>🧩 <a href="https://apify.com/abotapi/padmapper-rental-listings-scraper"><b>Padmapper Scraper</b></a><br>Scrape Padmapper apartment rentals across US/CA cities: rent, beds, baths, sqft...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/newhomesource-scraper"><b>NewHomeSource</b></a><br>Scrape new homes, floor plans, builders and communities from NewHomeSource.com. Search by...</td><td>🏨 <a href="https://apify.com/abotapi/hipflat-scraper"><b>Hipflat Scraper Thailand Property &amp; Projects</b></a><br>Scrape hipflat.co.th property listings and new-project data across Thailand: price, price...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/rent-com-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Search mode = pick city + state + filters below. URL mode = paste any rent.com URL refined in a browser (recommended for filters not exposed below).

## `locations` (type: `array`):

Cities to search. Add one or more entries — the scraper visits each city. State is the 2-letter US code. Search mode only.

## `propertyType` (type: `string`):

Which kind of rental to search. In Search mode this is encoded into the URL path segment (e.g. apartments → /<state>/<city>-apartments) and determines what gets fetched. In URL mode it never filters: each record's type comes from rent.com's own listing data first, then the type named in the pasted URL's path segment, and this field is used only as a last-resort fallback label when neither is present.

## `bedrooms` (type: `string`):

Exact bedroom count. Rent.com only exposes integer counts (no min/max ranges) on its SEO URLs. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `maxPrice` (type: `integer`):

Snapped to the nearest rent.com SEO band: 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 2000. Values above 2000 disable the max-price filter (rent.com has no canonical band above $2000). Optional. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `petFriendly` (type: `boolean`):

Show only pet-friendly listings. Rent.com URL filter is `pet-friendly` (combines cats AND dogs); separate cat/dog filters are not exposed. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `furnished` (type: `boolean`):

Show only furnished listings. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `luxury` (type: `boolean`):

Show only premium / luxury listings. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `dealsOnly` (type: `boolean`):

Show only listings with active rent specials (e.g. 1 month free). Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `incomeRestricted` (type: `boolean`):

Show only income-restricted (affordable housing) listings. Search mode only. Rent.com applies only ONE filter per search: if you set several, only the first in this order is applied (Bedrooms, Pet-friendly, Furnished, Luxury, Income-restricted, Deals only, Max price) and the log names the ones skipped.

## `urls` (type: `array`):

One or more full rent.com URLs: city searches (apartments, houses, condos, townhouses), near-me pages (rent.com/near-me/apartments), neighborhood pages, paginated /page-N, one filter segment (bedrooms, studio, price band, amenity) and single property pages. rent.com serves only one filter segment per search URL. Room-for-rent detail pages (rent.com/r/...) are not supported. State landing pages (for example rent.com/california, a list of cities with no listings) and rent-trends pages (a 6-listing teaser, not a search) are not supported and are skipped with a warning. Left untouched in URL mode, the field holds one example of each supported shape; they are scraped in order until Max listings is reached (with the default of 20, only the first example is reached). Pagination starts at the page in the URL and walks forward. Search-mode fields above have no effect on which listings are fetched, except Property type, which is used as a fallback label when neither the pasted URL nor rent.com's own listing data states one, see its own description.

## `maxPages` (type: `integer`):

How many SERP pages to walk per location/URL. Each page returns up to ~30 listings. Leave empty to walk every result page (still bounded by Max listings).

## `maxListings` (type: `integer`):

Stop after this many listings across all locations. 0 = no cap.

## `fetchDetails` (type: `boolean`):

When ON, fetch each listing's detail page for full description, complete amenity list, individual floor plans, ratings, and pet-policy details. Multiplies request count ~30× per SERP page. Default OFF — SERP cards already include 40+ fields. Detail fetches share the same warm session, so they consume no extra credits.

## `proxy` (type: `object`):

Rent.com fronts SERP pages with a US-only edge filter; non-US IPs almost always get rejected. Apify residential US passes naturally. Datacenter or non-US proxies will be SLOW or fail entirely.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue an unbounded walk across separate runs. Listings already collected there (matched by id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run. See `incrementalMode` below for recurring/scheduled monitoring instead.

## `incrementalMode` (type: `boolean`):

When ON, this run compares itself with the last successfully committed run of the SAME search (matched by `stateKey`, or an automatic key derived from your search/URL/filter settings) and adds `changeType` (NEW, UPDATED, UNCHANGED, REAPPEARED, EXPIRED), `changedFields`, `firstSeenAt`, `lastSeenAt` to every emitted record. What is compared: every listing field (rent range, beds/baths, availability, units text, special offers, deals, phone, floor plans, amenities, and the rest). What is excluded from the comparison (still present in the output): `scrapedAt` and the photo fields `photos`, `primaryImage`, `imageCount`, plus anything you list in `ignoreFieldsForChanges`. By default only NEW, UPDATED, and REAPPEARED are returned (see `emitUnchanged` and `emitExpired` below). No KV store or run ID pasting needed, this actor remembers state itself. Default OFF, so existing scheduled tasks keep their current output unchanged.

## `stateKey` (type: `string`):

Name this monitoring campaign so the same tracked search is recognized run over run, even if you change unrelated settings like `maxListings` or the proxy. Leave empty to derive one automatically from your search/URL/filter settings (two different searches never share state). Set it explicitly if you deliberately want to share state across differently-configured runs (for example, switching between Search mode and URL mode for the same properties).

## `emitUnchanged` (type: `boolean`):

When ON, incremental mode also outputs listings whose data did not change since the last run, tagged `changeType: UNCHANGED`. These rows ARE billed like any other dataset item. Default OFF: unchanged listings are scanned (so change detection still works) but not returned or charged.

## `emitExpired` (type: `boolean`):

When ON, incremental mode also outputs previously-tracked listings no longer found, tagged `changeType: EXPIRED`, but ONLY after a run that completed a full scan of the tracked search (no page cap or item cap cut it short, and no page was blocked). These rows ARE billed like any other dataset item. If a run cannot prove a complete scan, EXPIRED detection is skipped for that run and the prior tracked state is kept as-is (nothing is falsely marked gone). Default OFF.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Extra output fields to leave out of change detection, so a difference in them alone never marks a listing UPDATED and never appears in `changedFields`. The fields stay in the output. A plain name (`phoneText`) matches that field at any depth; a dotted path (`floorPlans.unitsAvailable`) matches that exact path, looking inside lists. Built-in exclusions (`scrapedAt`, `photos`, `primaryImage`, `imageCount`) always apply.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    {
      "city": "Los Angeles",
      "state": "CA"
    }
  ],
  "propertyType": "apartments",
  "bedrooms": "",
  "petFriendly": false,
  "furnished": false,
  "luxury": false,
  "dealsOnly": false,
  "incomeRestricted": false,
  "urls": [
    "https://www.rent.com/california/los-angeles-apartments",
    "https://www.rent.com/california/los-angeles-apartments/page-2",
    "https://www.rent.com/california/los-angeles-apartments?page=3",
    "https://www.rent.com/california/los-angeles-houses",
    "https://www.rent.com/california/los-angeles-condos",
    "https://www.rent.com/california/los-angeles-townhouses",
    "https://www.rent.com/california/los-angeles-apartments/2-bedroom",
    "https://www.rent.com/california/los-angeles-apartments/studio",
    "https://www.rent.com/california/los-angeles-apartments/max-price-2000",
    "https://www.rent.com/california/los-angeles-apartments/pet-friendly",
    "https://www.rent.com/california/los-angeles-apartments/hancock-park-neighborhood",
    "https://www.rent.com/texas/austin-apartments",
    "https://www.rent.com/apartment/cahuenga-apartments-los-angeles-ca-lc6041139"
  ],
  "maxListings": 20,
  "fetchDetails": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `floorPlans` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "locations": [
        {
            "city": "Los Angeles",
            "state": "CA"
        }
    ],
    "urls": [
        "https://www.rent.com/california/los-angeles-apartments",
        "https://www.rent.com/california/los-angeles-apartments/page-2",
        "https://www.rent.com/california/los-angeles-apartments?page=3",
        "https://www.rent.com/california/los-angeles-houses",
        "https://www.rent.com/california/los-angeles-condos",
        "https://www.rent.com/california/los-angeles-townhouses",
        "https://www.rent.com/california/los-angeles-apartments/2-bedroom",
        "https://www.rent.com/california/los-angeles-apartments/studio",
        "https://www.rent.com/california/los-angeles-apartments/max-price-2000",
        "https://www.rent.com/california/los-angeles-apartments/pet-friendly",
        "https://www.rent.com/california/los-angeles-apartments/hancock-park-neighborhood",
        "https://www.rent.com/texas/austin-apartments",
        "https://www.rent.com/apartment/cahuenga-apartments-los-angeles-ca-lc6041139"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/rent-com-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "locations": [{
            "city": "Los Angeles",
            "state": "CA",
        }],
    "urls": [
        "https://www.rent.com/california/los-angeles-apartments",
        "https://www.rent.com/california/los-angeles-apartments/page-2",
        "https://www.rent.com/california/los-angeles-apartments?page=3",
        "https://www.rent.com/california/los-angeles-houses",
        "https://www.rent.com/california/los-angeles-condos",
        "https://www.rent.com/california/los-angeles-townhouses",
        "https://www.rent.com/california/los-angeles-apartments/2-bedroom",
        "https://www.rent.com/california/los-angeles-apartments/studio",
        "https://www.rent.com/california/los-angeles-apartments/max-price-2000",
        "https://www.rent.com/california/los-angeles-apartments/pet-friendly",
        "https://www.rent.com/california/los-angeles-apartments/hancock-park-neighborhood",
        "https://www.rent.com/texas/austin-apartments",
        "https://www.rent.com/apartment/cahuenga-apartments-los-angeles-ca-lc6041139",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/rent-com-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "locations": [
    {
      "city": "Los Angeles",
      "state": "CA"
    }
  ],
  "urls": [
    "https://www.rent.com/california/los-angeles-apartments",
    "https://www.rent.com/california/los-angeles-apartments/page-2",
    "https://www.rent.com/california/los-angeles-apartments?page=3",
    "https://www.rent.com/california/los-angeles-houses",
    "https://www.rent.com/california/los-angeles-condos",
    "https://www.rent.com/california/los-angeles-townhouses",
    "https://www.rent.com/california/los-angeles-apartments/2-bedroom",
    "https://www.rent.com/california/los-angeles-apartments/studio",
    "https://www.rent.com/california/los-angeles-apartments/max-price-2000",
    "https://www.rent.com/california/los-angeles-apartments/pet-friendly",
    "https://www.rent.com/california/los-angeles-apartments/hancock-park-neighborhood",
    "https://www.rent.com/texas/austin-apartments",
    "https://www.rent.com/apartment/cahuenga-apartments-los-angeles-ca-lc6041139"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/rent-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/rent-com-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AUWYkWYGl1NmfAtND/builds/Zj9280Ri0uVOZANsl/openapi.json
