# Rent Data API - Rent Estimates, Comps, Market Rent Stats (`nabeelbaghoor/rent-data-api`) Actor

Get US rent estimates for any address: mean, median and percentile rents, the comparable rental listings behind them, rent history at an exact address, and bounded area rent statistics with census, HUD fair market rent and labor market data. Rank and screen rental markets by metric.

- **URL**: https://apify.com/nabeelbaghoor/rent-data-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 rent estimate returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Rent Data API - Rent Estimates, Comps, Market Rent Stats

Get a defensible rent estimate for any US address - mean, median and nine percentiles with the sample it rests on - plus every comparable listing behind it, the rent history at the exact address, and the market statistics and government data that put a single number in context.

### What this actor does

- **Rent estimates with the whole distribution, not one number.** Mean, median, minimum, maximum and the 5th, 10th, 20th, 25th, 50th, 75th, 80th, 90th and 95th percentiles, with the sample standard deviation, the number of comparable listings behind them, and the search radius actually used. A thin market gets a wider radius automatically, and the row says so, so you can tell a tight estimate from a stretched one.
- **The comparable listings behind the estimate.** One row per nearby rental with its address, coordinates, distance, advertised rent, square footage, rent per square foot, bedrooms, bathrooms, property type and the date it was last seen.
- **Outlier flags that reconcile the two.** The provider runs a Grubbs test over the comps and excludes the outliers from the statistics, but still returns them in the list. Every comp row carries that flag, so your own average can be made to match the published median instead of quietly disagreeing with it.
- **Rent history at an exact address.** Listings actually advertised at one address, with the mean staleness of the records, rather than the area around it.
- **Batch up to 1,000 addresses in one job.** Submitted asynchronously and polled to completion, with per-address status so an address with too little data is reported as such rather than silently missing.
- **Bounded market statistics.** Rent breakdowns by bedroom count and by property type for a metro, city, county, ZIP, neighborhood or school district, with the areas that contain any address you look up.
- **Census, HUD and labor market data on the same row.** American Community Survey demographics, HUD fair market rents, HUD housing affordability, local unemployment, industry employment and wages, building permits, and school district enrolment and per-pupil spending.
- **Rank and screen markets.** Order every metro, county or ZIP by one metric, or find the areas where several metrics all land inside your ranges at once.
- **Pay per result.** You are charged for rows carrying a real record. Addresses the provider cannot geocode and areas too thin to analyse are free.

### Bring your own key

This actor calls the provider with **your own API key**, generated in the API settings of your account. Paste it into the API key field, or set it as the `DATA_API_KEY` secret. Nothing runs on anyone else's credentials, and a run without a key ends cleanly with an explanation rather than failing.

API access needs an active Pro subscription with API access switched on. A pasted `Bearer ` prefix is stripped, so copying the whole header line instead of the key still works.

### Three wallets, and four free endpoints

The provider bills three separate balances - quickview, premium and pro report - and each endpoint draws on exactly one. An estimate spends a quickview credit; comps and address rents spend a premium credit. So a refusal for lack of credit on one mode says nothing about the others, and this actor names the balance that ran out rather than reporting a generic payment error.

Four things cost nothing: **area search**, **metric catalogue**, **account** and the rate limit check. Use them first. Resolve your place names to area slugs for free, read the metric catalogue to see which metrics your account is actually entitled to, then spend credits only on the questions that will answer.

### An address search and an area search are different questions

Setting an area slug does not narrow an address search - it replaces it. The provider then ignores the address, the coordinates **and the bedroom count**, and answers with unfiltered numbers for the whole area. That is often exactly what you want, and it is a bad surprise when it is not, so this actor refuses to send both and every row carries a `searchKind` and an `isWholeAreaResult` flag saying which question was actually asked.

### Example output

```json
{
  "recordType": "rentSummary",
  "requested": "1600 Pennsylvania Ave NW, Washington, DC",
  "searchKind": "address",
  "isWholeAreaResult": false,
  "found": true,
  "address": "1600 Pennsylvania Ave NW, Washington, DC 20500",
  "latitude": 38.897675,
  "longitude": -77.036547,
  "bedrooms": 2,
  "baths": "1.5 or more",
  "buildingType": "apartment",
  "lookBackDays": 365,
  "radiusMiles": 1.4,
  "meanRent": 3184,
  "medianRent": 3095,
  "minRent": 1950,
  "maxRent": 5400,
  "percentile25": 2695,
  "percentile50": 3095,
  "percentile75": 3600,
  "percentile90": 4250,
  "standardDeviation": 682.4,
  "sampleCount": 148,
  "containingAreas": ["zcta:20500-dc", "city:washington-dc", "metro:washington-arlington-alexandria-dc-va-md-wv"],
  "searchToken": "a1b2c3d4e5f6",
  "quickviewCreditsRemaining": 4812
}
```

### FAQ

#### What data does this rent estimate API return for an address?

For one address it returns the mean, median, minimum and maximum rent plus nine percentiles from the 5th to the 95th, the sample standard deviation, the number of comparable listings the statistics rest on, the radius searched, the geocoded address and coordinates, and the state, metro, county, ZIP and neighborhood areas that contain it. Add the comps mode and you also get every individual listing behind that estimate.

#### How do I get rent comps for a property?

Run **rent comps** mode with the address. It prices the address first and then reuses the search token the provider hands back to fetch the listings behind that price, which is the provider's own recommended path and avoids paying to geocode the same address twice. Each comp row carries the address, distance, advertised rent, square footage, rent per square foot, bedrooms, bathrooms, property type and last-seen date.

#### Why does my own average of the comps not match the published median?

Because they are not the same set. The provider tests the comps for statistical outliers and excludes the flagged ones from the mean, median and percentiles, while still returning them in the list so you can see what was thrown out. Filter on `isStatisticalOutlier` being false before averaging and the two agree.

#### What is the difference between rent summary, rent comps and address rents?

Rent summary is the aggregate rent for the area around an address. Rent comps is the individual listings that aggregate is built from. Address rents is the listing history recorded at that one exact address - a different question, and one most addresses have no answer to, because most properties are not individually tracked. When address rents comes back empty, rent summary is the mode that will answer.

#### How do I find a market's area slug?

Run **area search** with a place name such as `hyde park cincinnati` or `Austin TX`, or with a census FIPS, GEOID or ZCTA code. It returns every matching area with its slug, its area type, the number of listings backing it, its land area and its listing density. It costs no credits, so resolve your whole list before spending anything.

#### Which markets have the highest rents, incomes or lowest property taxes?

Use **rankings** for one metric - `acs.median_household_income` across every metro, say - or **screener** to find the areas where up to six metrics all sit inside your ranges at once. Write a constraint as `acs.median_household_income 75000-125000`, `acs.effective_property_tax_rate_pct <= 0.75` or `acs.median_gross_rent >= 1200`. A range typed backwards is corrected rather than sent, because the provider answers a backwards range with an empty result and no explanation.

#### Why did a ranking come back refused rather than empty?

There are two different refusals and they need different fixes. A 403 means your account is not entitled to that metric family, which is a conversation with the provider. A 422 means the metric exists but is not published for the kind of area you asked for, which is fixed by changing the area type. Run **metric catalogue** first: it is free and every metric comes back with an `entitled` flag and the list of area types it covers.

#### What government data comes with an area?

American Community Survey demographics, HUD fair market rents by bedroom count, HUD housing affordability, local unemployment from BLS LAUS, industry employment and wages from BLS QCEW, Census building permits, and for school districts, NCES enrolment and per-pupil finance. Whether each arrives depends on your account's access, and a source you cannot see is **omitted with no marker at all** - so an absent source means no data or no access and never zero. Every area row lists the sources that actually arrived.

#### Why does a fact for a ZIP code say it came from a county?

Because the provider falls back to the narrowest containing area that publishes the fact. Not every statistic exists at every level. Every fact row carries the source level and the slug of the area the number came from, so a county figure standing in for a ZIP is visible rather than assumed.

#### How many addresses can I price at once?

Up to 1,000 per batch job. The batch is queued, and this actor polls it to completion and emits one row per address, with an explicit status for addresses that could not be geocoded or had too few comparable listings. The provider checks your wallet covers the whole batch before accepting it, so a batch is either fully accepted or not charged at all.

#### What does it cost?

Pricing is per result. You pay for rows that carry a real record: an estimate, a comp, a listing, a matched area, an area bundle, a government fact, a ranked area or a catalogue metric. Addresses the provider cannot geocode, areas with too few listings, and place names that match nothing are all free. Apify platform usage is included in the per-result price.

#### Does the actor fail if my key is wrong?

No. A missing key, a refused key, an empty credit balance and an input that needs filling in all end the run cleanly with the reason as the run's status message. Only a real fault - a provider outage, or a bug here - fails a run.

### Keyword map

rent estimate API, rent data API, rental comps API, rent comps API, fair market rent API, median rent by ZIP code, average rent by city API, rental market data API, rent per square foot data, US rental listings data, rent percentile data, apartment rent estimate API, house rent estimate API, rent history by address, ACS demographics API, HUD fair market rent data, BLS unemployment by metro, market screener API, rental market rankings, real estate underwriting data.

# Actor input Schema

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

Rent summary prices one address, coordinate pair or area. Rent comps adds the individual listings behind that price. Address rents reads listings recorded at one exact address. Batch summary prices up to a thousand addresses in one job. Area search resolves place names to area slugs and costs no credits. Area facts reads one area in full. Rankings order areas by a metric and screener finds areas matching a whole profile. Metric catalogue and account cost nothing and tell you what your plan can do.

## `targets` (type: `array`):

One subject per line for rent summary, rent comps, address rents and batch summary. A street address including city and state, a "latitude,longitude" pair, or one of the provider's area slugs. An area slug answers with unfiltered whole-area numbers and ignores the bedroom filter, which is a different question from pricing one address.

## `address` (type: `string`):

A single street address, used when the list above is empty. Include the city and state for a reliable geocode.

## `latitude` (type: `string`):

Decimal latitude for a point search, between -90 and 90. Must be paired with a longitude, and is ignored when an address or an area slug is set.

## `longitude` (type: `string`):

Decimal longitude for a point search, between -180 and 180. Must be paired with a latitude.

## `areaSlug` (type: `string`):

One of the provider's bounded area identifiers, from area search mode. Setting this makes the provider ignore the address, the coordinates and the bedroom count, and answer with unfiltered numbers for the whole area.

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

Bedroom count to price, where 0 means a studio. Ignored on an area slug search, because the provider returns unfiltered whole-area numbers there.

## `baths` (type: `string`):

Bathroom filter. Leave blank to include every bath count.

## `buildingType` (type: `string`):

Limit the comparable listings to apartments or to houses. Leave blank for both.

## `lookBackDays` (type: `integer`):

How far back the comparable listings may reach, between 90 and 1460 days. The provider defaults to 365. A longer window finds more comps in thin markets and ages the estimate.

## `includeAreaFacts` (type: `boolean`):

Emit the curated census, HUD and labour statistics that ride along with a rent summary at no extra credit, one row per fact. Each row names the geographic level the number came from, because the provider falls back to the narrowest containing area that publishes it.

## `maxListingAgeDays` (type: `integer`):

Address rents mode only: days of listing history to include. The provider defaults to 30.

## `placeNames` (type: `array`):

Area search mode: one place name or census code per line, for example "hyde park cincinnati", "Austin TX" or "45208". Codes are sent as census identifiers rather than as free text, because a code searched as a name matches nothing.

## `areaSlugs` (type: `array`):

Area facts mode: one area slug per line. Area search mode finds them at no cost.

## `areaType` (type: `string`):

Which kind of area to rank, screen or disambiguate a census code to. City is an alias for place, ZIP for ZCTA, and CBSA for metro, which covers both metropolitan and micropolitan areas.

## `metric` (type: `string`):

Rankings mode: one metric key, for example acs.median\_household\_income. Metric catalogue mode lists every key with an entitled flag, and a metric your account is not entitled to is refused rather than returned empty.

## `withinSlug` (type: `string`):

Optional parent area slug to scope a ranking or a screen to. Leave blank to rank across the whole country.

## `order` (type: `string`):

Leave blank to use each metric's natural direction, which sorts income high to low and poverty low to high.

## `screenerFilters` (type: `array`):

Screener mode: one to six constraints, one per line, written as "acs.median\_household\_income 75000-125000", "acs.effective\_property\_tax\_rate\_pct <= 0.75" or "acs.median\_gross\_rent >= 1200". A range typed backwards is corrected rather than sent, because the provider answers it with an empty result and no explanation.

## `sortMetric` (type: `string`):

Which of the constrained metrics to order the matches by. Defaults to the first constraint.

## `maxResults` (type: `integer`):

Stop after this many rows. Each row is one charged result, so this is the ceiling on what a run can cost.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. Per-key rate limits depend on your tier, and a 429 is honoured with the wait the provider publishes.

## `baseUrl` (type: `string`):

Only set this if the provider has given you a different host. Leave blank for the standard one.

## `apiKey` (type: `string`):

Your own rent data API key. Generate one in the API settings of your account; API access needs an active Pro subscription with API access switched on. A pasted "Bearer " prefix is stripped. Leave blank to use the DATA\_API\_KEY environment secret instead.

## Actor input object example

```json
{
  "mode": "rentSummary",
  "bedrooms": "",
  "baths": "",
  "buildingType": "",
  "includeAreaFacts": false,
  "areaType": "metro",
  "order": "",
  "maxResults": 100,
  "requestsPerMinute": 60
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record, alongside the address, coordinate pair or area that produced it.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/rent-data-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/rent-data-api").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 '{}' |
apify call nabeelbaghoor/rent-data-api --silent --output-dataset

```

## MCP server setup

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

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/Jx7XgZLi7tF5YCnDV/builds/Yx1tsUbcGZZfMpsSs/openapi.json
