# Trulia Scraper — Property Listings & Details (`muhammadafzal/trulia-scraper`) Actor

Scrape public Trulia property listings and details: address, price, beds, baths, area, status, MLS, broker, images, coordinates, and source URL.

- **URL**: https://apify.com/muhammadafzal/trulia-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Real estate
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $48.00 / 1,000 property 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

## Trulia Scraper — Property Listings & Details

**Trulia Scraper** extracts public US property listings from Trulia search pages and individual property pages. It is designed for real-estate analysts, investors, researchers, relocation teams, and AI agents that need a predictable property dataset instead of raw page HTML. Each dataset item represents one property with a canonical Trulia URL, address, price, listing status, beds, baths, living area, property type, images, brokerage and MLS fields when available, coordinates, and extraction metadata.

The Actor accepts public sale, rental, sold, search, and property-detail URLs. It does not log into Trulia, access saved searches, call private Trulia APIs, or accept account cookies. Search results can be returned quickly from the search page's listing cards or enriched by opening each public property page.

### What data can I extract with Trulia Scraper?

| Field | Meaning |
|---|---|
| `listingId` | Stable ID parsed from the property URL or structured page data |
| `url` | Canonical public Trulia property URL |
| `sourceUrl` | Search or detail page where the property was found |
| `listingType` / `status` | Normalized type plus Trulia's displayed status |
| `address`, `city`, `state`, `zipCode` | Combined and structured location fields |
| `price`, `priceText`, `currency` | Numeric and display price values |
| `bedrooms`, `bathrooms` | Bed and bath counts, with `0` allowed for studios |
| `livingAreaSqft`, `lotSize`, `lotSizeUnit` | Interior and lot measurements |
| `propertyType`, `yearBuilt` | Property classification and construction year |
| `description`, `imageUrls` | Public description and deduplicated property images |
| `brokerName`, `mlsName`, `mlsId` | Public attribution and listing-source identifiers |
| `latitude`, `longitude`, `daysOnMarket`, `listedAt` | Market and geospatial fields when exposed |
| `detailsFetched` | Whether the individual property page was loaded |
| `attributes` | Additional compact primitive facts from structured data |
| `scrapedAt`, `warnings` | Extraction timestamp and item-specific caveats |

Unavailable fields are returned as `null` or an empty array. The shape remains stable across search-card and enriched-detail runs.

### When should I use it?

- Build a current sale or rental inventory for a city, state, ZIP code, or neighborhood.
- Compare asking prices, beds, baths, square footage, and listing status across properties.
- Feed normalized property records into a database, spreadsheet, BI dashboard, or valuation workflow.
- Monitor a bounded set of public Trulia property URLs for visible listing changes.
- Give an AI agent a compact, documented property entity instead of an unstructured web page.

Do not use this Actor for Trulia account pages, saved homes, private APIs, GraphQL endpoints, contact-form automation, or bypassing access controls. It does not estimate property values or verify MLS accuracy. Use the source URL and the relevant broker or MLS for decisions that require authoritative, up-to-date information.

### How to use Trulia Scraper

1. Copy one or more public Trulia search or property URLs into **Trulia URLs**.
2. Set **Maximum properties** to the largest result count you are willing to return and pay for.
3. Keep **Enrich property details** enabled for richer records, or disable it for faster search-card extraction.
4. The managed Actor automatically uses its protected access routes; you never supply proxy settings.
5. Run the Actor and download the default dataset as JSON, CSV, Excel, or another supported format.

Example input:

```json
{
  "startUrls": [
    { "url": "https://www.trulia.com/GA/Atlanta/" }
  ],
  "maxResults": 25,
  "maxPages": 1,
  "scrapeDetails": true,
  "requestDelaySecs": 1,
  "maxSessionRotations": 3
}
```

The default uses a public Atlanta sale-search URL; the prefill returns 3 properties from it. A direct property URL returns only that property. Search pages follow Trulia's numbered pagination up to `maxPages` and stop as soon as `maxResults` has been reached.

#### Run through the Apify API

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('muhammadafzal/trulia-scraper').call({
  startUrls: [{ url: 'https://www.trulia.com/GA/Atlanta/' }],
  maxResults: 10,
  maxPages: 1,
  scrapeDetails: true
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

The same input/output contract is available to AI agents through Apify's MCP integration. The Actor should be selected for public Trulia property research, not for generic web scraping or private Trulia account work.

### Output example

```json
{
  "listingId": "84572424",
  "url": "https://www.trulia.com/home/80591-sandpiper-ln-hermiston-or-97838-84572424",
  "sourceUrl": "https://www.trulia.com/for_sale/Hermiston,OR/",
  "status": "FOR SALE",
  "listingType": "for_sale",
  "propertyType": "SingleFamilyResidence",
  "address": "80591 Sandpiper Ln, Hermiston, OR 97838",
  "streetAddress": "80591 Sandpiper Ln",
  "city": "Hermiston",
  "state": "OR",
  "zipCode": "97838",
  "price": 399950,
  "priceText": "$399,950",
  "currency": "USD",
  "bedrooms": 3,
  "bathrooms": 2,
  "livingAreaSqft": 1782,
  "lotSize": 0.82,
  "lotSizeUnit": "acres",
  "yearBuilt": 1999,
  "description": "Move-in ready home on a private lot.",
  "imageUrls": ["https://photos.zillowstatic.com/fp/example-p_e.jpg"],
  "brokerName": "Real Broker",
  "mlsName": "RMLS (OR)",
  "mlsId": "735577088",
  "latitude": null,
  "longitude": null,
  "daysOnMarket": null,
  "listedAt": null,
  "detailsFetched": true,
  "attributes": {},
  "scrapedAt": "2026-08-11T09:00:00.000Z",
  "warnings": []
}
```

Run diagnostics are stored separately in the `OUTPUT` key. They distinguish successful, successful-with-warnings, empty, blocked, and invalid-input outcomes. Diagnostic pseudo-records are never mixed into the homogeneous property dataset.

### Pricing and cost controls

This Actor uses **pay-per-event (PPE)** pricing with all platform usage included. There is no separate platform usage fee passed to users.

#### Event prices by tier

| Event | Primary | FREE | BRONZE (2.5% off) | SILVER (5% off) | GOLD (20% off) | Description |
|---|:---:|---:|---:|---:|---:|---|
| `apify-actor-start` | No | $0.010001 | $0.00975 | $0.0095 | $0.008 | Synthetic start event charged once per started GB of allocated memory (1 event at the 256 MB default). |
| `property-result` | **Yes** | $0.060001 | $0.0585 | $0.057 | $0.048 | Charged once only after one schema-valid, deduplicated property record is stored in the default dataset. |

#### Representative run estimates (at 256 MB default memory)

| Run scope | FREE tier total | GOLD tier total | Details |
|---|---:|---:|---|
| Single property canary (1 item) | ~$0.070 | ~$0.056 | 1 start event + 1 property result |
| Small batch (10 items) | ~$0.610 | ~$0.488 | 1 start event + 10 property results |
| Standard search page (25 items) | ~$1.510 | ~$1.208 | 1 start event + 25 property results |

- **Failed, blocked, or empty runs**: If all target requests are blocked or no property matches exist, zero `property-result` events are billed.
- **Deduplication**: Duplicate property URLs within a run are skipped and never charged twice.
- **Budget guard**: Honor `maxResults` and Apify's max total charge limit. The Actor stops cleanly before exceeding limits.

### Reliability and limitations

Trulia protects public pages with a bot-protection service that answers some IP addresses with a `403` block page. The Actor reads the public HTML pages over plain HTTP, with no browser, through owner-managed US access routes stored as protected secrets; callers cannot supply proxy settings. It never interacts with or solves a verification challenge. When a page comes back blocked, the Actor drops that session and requests the page again on a fresh session, cheapest route first, up to `maxSessionRotations` extra sessions (default 3). A page still blocked after that budget is skipped and reported in `OUTPUT`, together with per-route request and block counts in `accessPath`.

Page count, result count, retries and run duration are bounded. A 200 response with no records from a page expected to contain properties is treated as an extraction or access regression. If every target request is blocked, the run ends FAILED with a terminal `BLOCKED` explanation in the status message and `OUTPUT`, and zero `property-result` charges. Valid no-match pages finish with an `EMPTY` output instead.

Websites and listing feeds change. Some fields may differ by property type, MLS provider, market, or listing status. Search-card-only mode intentionally contains fewer details. Review `warnings`, `detailsFetched`, `OUTPUT`, and source URLs before using the data for financial, legal, lending, appraisal, or housing decisions.

### Other dedicated scrapers

- [Realtor Lead Scraper](https://apify.com/muhammadafzal/realtor-lead-scraper)
- [Fast Realtor.com Agents Scraper](https://apify.com/muhammadafzal/fast-realtor-agents-api-scraper)
- [Apartments.com Email Scraper](https://apify.com/muhammadafzal/apartments-com-email-scraper)
- [Idealista Scraper](https://apify.com/muhammadafzal/idealista-scraper)
- [Domain.com.au Scraper](https://apify.com/muhammadafzal/domain-scraper)
- [Craigslist Scraper](https://apify.com/muhammadafzal/craigslist-scraper)
- [Google Maps Scraper](https://apify.com/muhammadafzal/google-maps-scraper)
- [Email Address Validator](https://apify.com/muhammadafzal/email-address-validator)

### FAQ

#### Does Trulia Scraper work right now?

Yes. Since 2026-10-30 the Actor reads Trulia's public pages over HTTP instead of a browser. A blocked page is retried on a fresh access session within a fixed budget and is never solved. If every request stays blocked, the run ends FAILED with a `BLOCKED` explanation in `OUTPUT` and no `property-result` charges.

#### How many results can I scrape with Trulia Scraper?

The input accepts 1–500 properties per run. Actual output depends on visible matches, pagination, the run timeout, proxy access, and your event budget. Start with 10–25 enriched properties, then increase the cap after measuring your target market.

#### Can I integrate Trulia Scraper with other apps?

Yes. Connect the default dataset to Make, Zapier, webhooks, cloud storage, databases, spreadsheets, or your own application through Apify integrations and APIs.

#### Can I use Trulia Scraper with the Apify API?

Yes. Start runs with the Apify REST API or `apify-client`, then read the default dataset using the run's `defaultDatasetId`.

#### Can I use Trulia Scraper through an MCP Server?

Yes. Apify's MCP tooling can discover the Actor's input and output schemas. Use it when an agent needs public Trulia property records with predictable fields and explicit cost limits.

#### Do I need proxies to scrape Trulia?

Usually. Trulia currently blocks many direct and datacenter requests. The managed Actor supplies its residential access route automatically; callers do not provide proxy settings or credentials.

#### Is it legal to scrape Trulia data?

Scraping legality depends on jurisdiction, the data, your access method, and intended use. Scrape only public information you are authorized to collect, follow applicable laws and Trulia's current terms and robots guidance, respect intellectual-property and privacy rights, and obtain legal advice for regulated or high-risk uses. Trulia and Zillow are trademarks of their respective owners; this Actor is not affiliated with or endorsed by them.

#### Your feedback

Report reproducible issues with the redacted input, run ID, affected URL type, final status message, and whether detail enrichment was enabled. Do not post proxy credentials, tokens, cookies, or private personal data.

Last verified: 2026-10-30

# Changelog

This Actor's version history is a separate document: https://apify.com/muhammadafzal/trulia-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Use this for public Trulia search or property pages. Accepts https://www.trulia.com/GA/Atlanta/, https://www.trulia.com/for_sale/Atlanta,GA/, and https://www.trulia.com/home/... examples. Search pages discover many homes; detail pages return one property. Private API and account URLs are rejected.

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

Use this to cap returned properties and result charges. The default is 25; valid range is 1–500. One stored schema-valid property consumes one property-result event; failed, blocked, duplicate, and schema-invalid records are not billed.

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

Use this for Trulia search URLs to limit pagination. The default is 1; valid range is 1–20. This does not limit individual detail pages supplied directly in Trulia URLs.

## `scrapeDetails` (type: `boolean`):

Use this when complete property fields matter. When enabled (default), each search result opens its public Trulia property page for richer details. Disable it for faster search-card extraction with fewer fields and lower proxy usage.

## `requestDelaySecs` (type: `integer`):

Use this to pace Trulia page loads within one sticky session. Default 1 second; valid range 0–10. Higher values reduce request rate but increase total run time.

## `maxSessionRotations` (type: `integer`):

Use this to bound how many fresh access sessions one page may use after Trulia answers with a block page, a temporary server error (HTTP 5xx), or a network error. Default 3; valid range 0–6. The Actor never interacts with or solves a verification challenge: a blocked session is dropped, and a page still blocked after this budget is skipped and reported in OUTPUT.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.trulia.com/GA/Atlanta/"
    }
  ],
  "maxResults": 3,
  "maxPages": 1,
  "scrapeDetails": true,
  "requestDelaySecs": 1,
  "maxSessionRotations": 3
}
```

# Actor output Schema

## `results` (type: `string`):

Normalized Trulia property records as JSON dataset items.

## `resultsCsv` (type: `string`):

The same normalized property records exported as CSV.

## `runOutput` (type: `string`):

Terminal outcome, request counts, delivered and billed result totals, and warnings.

## `consoleRun` (type: `string`):

Open the run in Apify Console to inspect logs and storage.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.trulia.com/GA/Atlanta/"
        }
    ],
    "maxResults": 3,
    "maxPages": 1,
    "scrapeDetails": true,
    "requestDelaySecs": 1,
    "maxSessionRotations": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/trulia-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 = {
    "startUrls": [{ "url": "https://www.trulia.com/GA/Atlanta/" }],
    "maxResults": 3,
    "maxPages": 1,
    "scrapeDetails": True,
    "requestDelaySecs": 1,
    "maxSessionRotations": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/trulia-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 '{
  "startUrls": [
    {
      "url": "https://www.trulia.com/GA/Atlanta/"
    }
  ],
  "maxResults": 3,
  "maxPages": 1,
  "scrapeDetails": true,
  "requestDelaySecs": 1,
  "maxSessionRotations": 3
}' |
apify call muhammadafzal/trulia-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/trulia-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/XlrXfm6LlaNbkoVjh/builds/CdVY1RmDFOhuJqDuJ/openapi.json
