# Trulia New Listings Scraper (US homes for sale) (`superslowsloth/trulia-listings`) Actor

Newest-first US homes for sale from Trulia, by city or search URL. One flat row per home: address, price, beds, baths, sqft, lot size, property type, date listed, status, agent and broker, MLS number, coordinates and photo.

- **URL**: https://apify.com/superslowsloth/trulia-listings.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 listing scrapeds

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?

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

## Trulia New Listings Scraper

A newest-first feed of US homes for sale. Give it cities (`"Denver, CO"`) or
Trulia search URLs and it returns the homes Trulia lists first, each as one flat
row: address, asking price, beds, baths, floor area, lot size, property type,
the date it was listed, its status, the listing agent and broker, the MLS
number, coordinates and a photo.

Built to be called on a schedule or by an agent: small input, one row per home,
no nested objects, no HTML. Run it daily with a modest `maxItems` and you have a
"what just came on the market" feed.

### Input

| field | meaning |
|---|---|
| `locations` | One per line: `"Denver, CO"` (city and two-letter state) or a full trulia.com search URL |
| `maxItems` | Homes per location, newest first. Default 100, ceiling 1000 — see limits |
| `requestIntervalSecs` | Pause between result pages. Default 1 |
| `proxyConfiguration` | Apify proxy, on by default |

A pasted search URL keeps whatever filters and sort are already on it (price,
bedrooms, property type, `price;a_sort`), so that is how to filter: set the
filters on trulia.com, paste the address bar. For a plain `"City, ST"` Trulia's
default order is already newest first.

City names are Trulia's own. `"Colorado Springs, CO"` and `"Winston-Salem, NC"`
work; `"St. Louis, MO"` does not (Trulia spells it `Saint Louis`). Trulia does
not say so when it cannot place a city — it quietly shows the whole state — so
the actor compares where Trulia landed with where it was sent and reports a
failure instead of returning 37,000 homes from the wrong place.

### Output

One item per home:

| field | meaning |
|---|---|
| `id` | Trulia's id: the number at the end of the listing URL |
| `url` | The listing on trulia.com, absolute |
| `date_listed` | When the listing went live, ISO 8601 with UTC offset |
| `listing_status` | `for sale`, `coming soon`, `for sale by owner`, `foreclosure`, `trulia preview` |
| `address`, `street_address`, `city`, `state`, `zipcode` | The address, whole and split |
| `latitude`, `longitude` | Coordinates |
| `price` | Asking price in whole US dollars, or `null` — see below |
| `price_text` | The price exactly as Trulia shows it: `"$310,000"`, `"Price Unknown"`, `"$1,075,300 (Est.)"` |
| `currency` | `USD` when `price` is present |
| `beds`, `baths` | Counts. A half bath is `0.5`; a studio is `0.0` |
| `living_area_sqft` | Interior floor area |
| `lot_size`, `lot_size_unit` | Lot size and **the unit it was measured in** (`acres` or `sqft`) |
| `property_type` | `SINGLE_FAMILY_HOME`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `LOT_LAND`, `COOP`, `APARTMENT`, `MOBILE_MANUFACTURED` |
| `listing_agent`, `broker_name`, `mls_number` | Who listed it. `null` for owner-listed homes |
| `image_url` | Largest photo on the card |
| `tags` | Trulia's badges: `NEW_LISTING`, `OPEN_HOUSE`, `COMING_SOON`, `NEW_CONSTRUCTION`, `AUCTION`, `FOR_SALE_BY_OWNER`, `TRULIA_PREVIEW`, `LOT_SIZE` |
| `search_location` | The location string or URL this row came from, echoed back |

#### Nulls, not zeros

Trulia does not show every value on every home, and a missing value is `null`,
never `0`. In a 400-card sample across ten searches about 15% had no bedroom
count (lots and land), 17% no bathroom count and 20% no floor area. A few had no
price at all.

`price` is only ever an asking price. Auction and foreclosure cards on Trulia
show an estimated value instead; that estimate goes in `price_text` (with
`(Est.)`) and `price` stays `null`, because the seller is not asking that. A
card that says `Price Unknown` or `Contact` is `null` in both.

Builder floor-plan cards that Trulia mixes into results (a plan a builder will
build, with a price range and no listing date) are not homes for sale and are
left out. The run log counts them.

#### There is no days-on-market column

A search card carries the date it was listed, and a "NEW - 3 HRS AGO" badge,
but not a day count. Subtract `date_listed` from the day you read the row; baking
a count into the data would bake in the moment of the scrape.

### Limits worth knowing before you run it

- **1,000 homes per location, always.** Trulia serves 40 homes per page and stops
  at page 25. Past that it answers HTTP 200 with page 1 again and no error; the
  actor reads the page number back and stops, and the run log lists locations
  that stopped there. `New York, NY` matches 22,000+ homes. To go deeper, give
  several narrower locations or filtered search URLs.
- **Only for-sale search.** Rentals and recently-sold pages are not read.
- **Trulia refuses non-browser clients.** A plain HTTP request from a cloud
  address gets a PerimeterX "Access to this page has been denied" page (HTTP
  403\). The actor presents a real Chrome TLS fingerprint instead, and treats any
  page that arrives without the data in it as a refusal: it switches to a fresh
  proxy address and retries rather than reporting an empty success.
- **Duplicates across pages and locations are skipped, and not charged.** A home
  that appears twice is delivered once.
- **Trulia can change its page at any time.** The data is read from the page's
  embedded JSON, which is not a published API.

### Pricing

Pay per event: a small charge when the run starts, plus one charge per home
delivered. Skipped duplicates and floor plans are not charged, and a run that
returns nothing charges only the start event.

# Actor input Schema

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

Where to look, one per line. Either a city and two-letter state ("Denver, CO", "Colorado Springs, CO") or a full trulia.com search URL pasted from your browser (for example one with price or bedroom filters already applied, which are kept). Each location is read separately; a home that two locations both return is delivered once, under the first. A city name Trulia does not recognise is reported as a failure rather than returned as the whole state - use Trulia's own spelling ("Saint Louis, MO", not "St. Louis, MO").

## `maxItems` (type: `integer`):

Read at most this many homes for each location, newest first. Trulia serves 40 homes per page and stops at page 25, so 1000 is the ceiling for any one location however many homes match; the run log reports how many matched. For a larger area, add several narrower locations or filtered search URLs.

## `requestIntervalSecs` (type: `integer`):

How long to wait between result pages. Trulia sits behind an anti-bot service that refuses addresses it dislikes; the run answers a refusal by switching to a fresh address and retrying, and a longer pause trades wall-clock time for fewer retries.

## `proxyConfiguration` (type: `object`):

Apify proxy (automatic datacenter exits) is the default. A proxy is what lets a refused request be retried from a fresh address. Trulia refuses plain HTTP clients outright, so the run presents a real Chrome TLS fingerprint instead.

## Actor input object example

```json
{
  "locations": [
    "Denver, CO"
  ],
  "maxItems": 100,
  "requestIntervalSecs": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (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 = {
    "locations": [
        "Denver, CO"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/trulia-listings").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 = {
    "locations": ["Denver, CO"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/trulia-listings").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 '{
  "locations": [
    "Denver, CO"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/trulia-listings --silent --output-dataset

```

## MCP server setup

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

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/hjVhz0rvtfpqazuPf/builds/TR6kTx7gCM9tjtUm7/openapi.json
