Trulia Scraper - Property Listings, Prices, Agents & History
Pricing
from $1.60 / 1,000 listing scrapeds
Trulia Scraper - Property Listings, Prices, Agents & History
Scrape Trulia.com property listings by location, filters, or URL. Extract prices, beds, baths, square footage, addresses, GPS coordinates, photos, agents, and brokers, plus detailed price and tax history, property features, and open house information.
Pricing
from $1.60 / 1,000 listing scrapeds
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
8 days ago
Last modified
Categories
Features
Share
Trulia Scraper: Property Listings, Prices, Photos & Agent Contacts
Trulia Scraper turns Trulia into a clean property data feed for the United States. Search any US location for homes for sale, for rent, or recently sold, or paste Trulia search and property links you already have. Every listing comes back as one record with price, beds, baths, square footage, full address, GPS coordinates, photo gallery, status tags, and the listing agent and broker. Turn on detail mode to also pull price history, tax history, the full feature list, open houses, agent contact, and affordability data straight from each property page, then export to JSON, CSV or Excel, or read it through the API.
Why This Scraper?
- Rich cards out of the box. Search results already carry price, beds, baths, size, full address, neighborhood, GPS coordinates, photo gallery, status tags and the listing agent and broker name, with no extra fetch needed.
- Optional deep detail. One toggle adds price history, tax history, the full feature list, open houses, agent and broker contact, local protections, affordability data and estimated rent from the property page.
- Three listing channels. For sale, for rent, and recently sold, all from the same search fields.
- Real keyword filter. Narrow a location to listings whose text mentions a term such as pool, waterfront or garage.
- Two ways to start. Build a search from simple fields, or paste Trulia search and property links you already have, with automatic pagination on search links.
- Predictable runs. Detail mode is off by default so a standard run stays fast and low cost, and Max items keeps every run's size and spend capped.
- Built for schedules. Resume continues one interrupted crawl, and Incremental mode turns a recurring search into a feed of only what is new, updated or reappeared.
Use Cases
- Real estate investors and flippers: track new listings and price drops for sale in target neighborhoods.
- Rental market research: collect current for-rent inventory and pricing across a metro area or ZIP code.
- Market analysts and appraisers: build historical comps from recently sold listings, including price and sale history.
- PropTech and data teams: feed a normalized property dataset into an internal tool, model or dashboard.
- Relocation and lead-generation sites: enrich listing pages with fresh price, photo and agent contact data.
- Agents and brokers: monitor a search for new listings or status changes and get only the changes on a schedule.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | "00000001" |
url | "https://www.trulia.com/home/sample-address-ny-10000-00000001" |
listingType | "FOR_SALE" (also "FOR_RENT", "SOLD") |
propertyType | "SINGLE_FAMILY_HOME" |
price / formattedPrice | 750000 / "$750,000" |
streetAddress | "123 Sample Street" |
city / state / zipCode | "Sampletown" / "NY" / "10000" |
neighborhood | "Sample Heights" |
latitude / longitude | 40.0000 / -73.0000 |
bedrooms / bathrooms | 3 / 2 |
floorSpace | "1,800 sqft" |
lotSize | "0.25 acres" |
listingAgentName | "Agent Name" |
brokerName | "Sample Realty" |
heroImage | listing's main photo URL |
photos | array of gallery photo URLs |
tags | ["NEW", "OPEN SUN"] (status badges) |
dateListed | "2026-01-01" |
description | listing description text |
scrapedAt | "2026-01-01T00:00:00.000Z" |
With Fetch property details enabled, each record also gains priceHistory, taxes, features, openHouses, providerDetails (agent and broker contact), localProtections, affordability, estimatedRent, totalPhotoCount, detailFetched (whether this record's own detail fetch actually succeeded this run), plus the full homeDetails object.
Incremental mode only. When incrementalMode is on, a returned record also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields (populated only for UPDATED), firstSeenAt and lastSeenAt. An EXPIRED row is a tombstone built from the last snapshot this actor collected, not a fresh re-fetch of a listing that is gone.
How to Use
- Pick a Start mode: search by location, or paste direct Trulia URLs.
- In search mode, fill in Location, Listing type and optionally Keyword and Sort; in URL mode, paste one or more Trulia search or property links.
- Turn on Fetch property details if you need price history, taxes, features or agent contact, and set Max items to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Basic search:
{"mode": "search","searchLocation": "Austin,TX","searchListingType": "FOR_SALE","maxItems": 50}
Search with keyword and sort:
{"mode": "search","searchLocation": "Miami,FL","searchListingType": "FOR_SALE","searchKeyword": "pool","searchSort": "PRICE_LOW_TO_HIGH","maxItems": 100}
For rent, with full detail enrichment:
{"mode": "search","searchLocation": "Seattle,WA","searchListingType": "FOR_RENT","fetchDetails": true,"maxItems": 40}
Direct URLs (search URLs paginate, property URLs return one record each):
{"mode": "url","startUrls": ["https://www.trulia.com/sold/Denver,CO/","https://www.trulia.com/home/sample-address-co-80000-00000002"],"maxItems": 60}
Supported URL shapes (URL mode). Paste any of these; search shapes paginate automatically and property shapes return one record each. m.trulia.com links are converted to www.trulia.com.
| Shape | Example |
|---|---|
| for sale | https://www.trulia.com/for_sale/Austin,TX/ |
| for rent | https://www.trulia.com/for_rent/Austin,TX/ |
| sold | https://www.trulia.com/sold/Austin,TX/ |
| paginated | https://www.trulia.com/for_rent/Austin,TX/2_p/ |
| keyword | https://www.trulia.com/for_sale/Austin,TX/pool_keyword/ |
| sort price asc | https://www.trulia.com/for_sale/Austin,TX/price;a_sort/ |
| sort plus page | https://www.trulia.com/for_sale/Austin,TX/2_p/price;a_sort/ |
| beds | https://www.trulia.com/for_sale/Austin,TX/2p_beds/ |
| type | https://www.trulia.com/for_sale/Austin,TX/SINGLE-FAMILY_HOME_type/ |
| state city canonical | https://www.trulia.com/TX/Austin/ |
| neighborhood | https://www.trulia.com/TX/Austin,Downtown/ |
| zip canonical | https://www.trulia.com/TX/Austin/78701/ |
| zip legacy | https://www.trulia.com/for_sale/78701_zip/ |
| mobile host | https://m.trulia.com/for_sale/Austin,TX/ |
| home detail | https://www.trulia.com/home/11221-gadsen-ln-105-austin-tx-78754-338244892 |
| legacy p detail | https://www.trulia.com/p/tx/austin/11221-gadsen-ln-105-austin-tx-78754--338244892 |
| building detail | https://www.trulia.com/building/33hundred-3300-wells-branch-pkwy-austin-tx-78728-1146835547 |
| paginated sold | https://www.trulia.com/sold/Austin,TX/2_p/ |
| paginated canonical | https://www.trulia.com/TX/Austin/2_p/ |
| state page | https://www.trulia.com/TX/ |
| new homes | https://www.trulia.com/for_sale/Austin,TX/new_homes_lt/ |
| feature landing | https://www.trulia.com/for_sale/Austin,TX/backyard/ |
| price range plus beds plus sort | https://www.trulia.com/for_sale/Austin,TX/0-500000_price/3p_beds/date;d_sort/ |
| canonical price landing | https://www.trulia.com/TX/Austin/homes-for-sale-under-500000/ |
| query sort | https://www.trulia.com/for_sale/Austin,TX/?sort=newest |
| query sort (price) | https://www.trulia.com/for_sale/Austin,TX/?sort=price_desc |
| keyword plus sort plus page | https://www.trulia.com/for_sale/Austin,TX/pool_keyword/price;a_sort/2_p/ |
Canonical state, city, neighborhood and ZIP pages carry no listing type and are read as for-sale. A ?query (for example ?sort=newest) is kept and the page segment is placed in the path in front of it (/2_p/?sort=newest). The Trulia home page (trulia.com) and bare feature paths such as trulia.com/backyard/ are not listing searches and are skipped with a warning; use /for_sale/<place>/backyard/ instead. A page segment in front of a sort (2_p/price;a_sort/) is honored and the walk continues from that page. A URL that is not a supported Trulia shape (another site, or /home/<numeric-id> which Trulia answers with HTTP 410) is skipped with a warning in the log. Default behaviour: if you switch to URL mode and leave Trulia URLs untouched, the actor now scrapes the 17 example URLs above (split across Max items) instead of failing with no URLs; clear the list and paste your own for a normal run. In search mode, the Location accepts Austin, TX, Austin TX or Austin,TX; a location that returns nothing logs an error.
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/trulia-scraper").call(run_input={"mode": "search","searchLocation": "Austin,TX","searchListingType": "FOR_SALE","maxItems": 50,})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["streetAddress"], listing["formattedPrice"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/trulia-scraper').call({mode: 'search',searchLocation: 'Austin,TX',searchListingType: 'FOR_SALE',maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Max items and Max pages
Max items is the run's overall cap on listings. When you paste several URLs, it is split evenly between them (each URL gets Max items divided by the number of URLs, rounded up), so every URL is represented. Max pages is an optional extra safety cap on pages walked per search or URL (Trulia serves 40 listings per page); leave it empty to walk every result page and let Max items decide when to stop.
Listings are deduplicated once across the whole run, not per URL, so the same listing is never returned twice even if two of your URLs overlap. Known limitation, URL mode with two or more URLs only: when a URL's share of Max items runs out partway through a results page, the listings on that page that were not collected are still marked as already seen for the rest of the run. If a later URL in the same run reaches one of those listings (two overlapping search areas, or a property URL for a home that appeared on that cut page), it is skipped without a warning and never returned by either URL, so the run can end with fewer listings than Max items allows. Raising Max items does not reliably avoid this, because a URL's share almost always ends mid-page. To avoid it, set Max items to 0 (unlimited) and bound the run with Max pages instead, or run overlapping URLs as separate runs. Search mode is not affected, because it runs one search per run.
Resume and recurring updates
Resume (resumeFromRunId) continues one specific interrupted or previous run: paste its run ID or dataset ID and this run skips listings already collected there, returning only what is left. Because Resume reads the listings actually saved in that earlier dataset, it is not affected by the limitation above. An automatic same-run checkpoint also lets a run continue after a platform migration or the Resurrect button, without any input needed. That checkpoint stores the run's "already seen" list, so it carries the limitation above into the continued run, and listings from the page being processed at the exact moment of a migration can be marked as seen before they were saved and then skipped. If a migrated or resurrected run looks short, start a new run with Resume pointed at it to collect only what is missing.
Incremental mode (incrementalMode) is for scheduling the same search or URL set repeatedly, for example daily. The actor remembers the previous run of that same search by itself, so no run ID needs to be pasted. The first run returns everything as NEW; later runs return only NEW, UPDATED and REAPPEARED listings by default, and duplicates or unchanged listings are suppressed and not billed. Turn on emitUnchanged or emitExpired only when you also want those rows returned, and billed for. State is scoped per location or URL, listing type, keyword, sort and the fetchDetails setting automatically; set stateKey to name or deliberately share a monitoring campaign. With fetchDetails on, a listing's property page is still fetched every run so change detection stays accurate, but the enrichment charge only applies to listings actually returned; a suppressed unchanged listing is neither pushed nor billed.
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.
- Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
- For Notion, also set
notionParentPageUrlto 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 builds Trulia search URLs from the filters below; url takes Trulia search or property URLs you already have. |
searchLocation | string | New_York,NY | Search mode only. A US location as City,STATE. Spaces are converted to underscores automatically. |
searchListingType | string | FOR_SALE | Search mode only. FOR_SALE, FOR_RENT, or SOLD. |
searchKeyword | string | (empty) | Search mode only. Narrows results to listings whose text mentions this keyword. Leave empty for no keyword filter. |
searchSort | string | RECOMMENDED | Search mode only. RECOMMENDED, NEWEST, PRICE_LOW_TO_HIGH, or PRICE_HIGH_TO_LOW. NEWEST is currently served in the recommended order because Trulia no longer offers a newest-first order (the run logs a warning); use incrementalMode to catch new listings. Trulia may place a few promoted listings ahead of the chosen order. |
minBeds | integer | (empty) | Search mode only. Keep listings with at least this many bedrooms (1-5). |
minBaths | integer | (empty) | Search mode only. Keep listings with at least this many bathrooms (1-4). Trulia applies this filter on its side and counts half-baths, so a listing with one and a half baths can appear under 2 or more. It works with or without minBeds. |
propertyType | string | (empty) | Search mode only. SINGLE_FAMILY, CONDO, TOWNHOUSE, MULTI_FAMILY, LAND or MOBILE_MANUFACTURED. |
searchZip | string | (empty) | Search mode only. 5-digit ZIP code; replaces searchLocation when set. |
startUrls | array | the 17 example URLs above | URL mode only. Trulia search URLs (paginated automatically) or property/home URLs (fetched as single detail records). Multiple URLs supported. |
fetchDetails | boolean | false | Include price history, tax history, the full feature list, open houses, listing agent and broker contact, affordability and more from the property page. Billed per enriched listing that is actually returned. |
maxItems | integer | 20 | Maximum number of listings to scrape across all searches and URLs in this run. Set 0 for unlimited. |
maxPages | integer | (unlimited) | Optional safety cap on search pages to walk per location or URL (40 listings per page). Leave empty to walk every result page; the run still stops at Max items. |
resumeFromRunId | string | (none) | Paste a previous run ID or dataset ID from this actor to continue a large crawl without returning or charging for listings already collected there. For recurring monitoring of the same search, use Incremental mode instead. |
incrementalMode | boolean | false | Turn on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED listings. UPDATED means any field of the stored record changed; only the relative "last checked" text and the MLS refresh stamp inside the listing source are never compared, plus any field you list in ignoreFieldsForChanges. |
stateKey | string | (none) | Optional. Names this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Left empty, the actor derives a key automatically from the location or URLs, listing type, keyword, sort, and fetchDetails settings. |
emitUnchanged | boolean | false | Incremental mode only. Also return (and bill for) listings unchanged since the last run, marked UNCHANGED. |
emitExpired | boolean | false | Incremental mode only. Also return (and bill for) listings from a previous run no longer found, marked EXPIRED, once a run has fully scanned the search (not capped, not a resume, not a pasted page-N start, not trimmed by Max pages). |
changeScope | string | all | Incremental mode only. all compares the whole record. priceAndStock compares only price, price type, currency, listing type, current status and the price-change block, so description, photo, tag or agent changes never return an UPDATED row. |
compactUpdates | boolean | false | Incremental mode only. UPDATED and EXPIRED rows become short (ids, url, location, current price and status, priceChanges, variantChanges). NEW rows stay complete. The Fetch details charge does not apply to a compact row, because it carries no detail data. |
expireAfterMissedScans | integer | 1 | Incremental mode with emitExpired only. A listing is marked EXPIRED only after it was missing from this many complete scans in a row. EXPIRED means no longer found in the results, not proof of delisting; use the status fields for availability. |
ignoreFieldsForChanges | array | (none) | Incremental mode only. Field names (dotted for nested fields, for example provider.logoUrl) excluded from UPDATED detection and changedFields. The fields stay in the output. |
proxy | object | Apify proxy, United States | Connection settings. The default reads search results and home pages over a datacenter connection pinned to the United States; building pages use Apify Residential. Neither connection is accepted on every try, so the actor retries on other exits. You can select Apify Residential (US) or supply your own proxy URLs. Saved inputs that already select Residential keep it. |
mcpConnectors | array | (none) | Optionally send a summary of each record to apps you authorized under Integrations (Notion, Linear, Airtable, or Apify). |
notionParentPageUrl | string | (none) | Notion connector only. URL or id of the Notion page under which item pages are created. Ignored by other connectors. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run, from 1 to 1000. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "00000001","url": "https://www.trulia.com/home/sample-address-ny-10000-00000001","listingType": "FOR_SALE","propertyType": "SINGLE_FAMILY_HOME","price": 750000,"formattedPrice": "$750,000","streetAddress": "123 Sample Street","city": "Sampletown","state": "NY","zipCode": "10000","neighborhood": "Sample Heights","latitude": 40.0,"longitude": -73.0,"bedrooms": 3,"bathrooms": 2,"floorSpace": "1,800 sqft","lotSize": "0.25 acres","listingAgentName": "Agent Name","brokerName": "Sample Realty","heroImage": "https://www.trulia.com/pictures/thumbs_4/sample/00000000-full.jpg","photos": ["https://www.trulia.com/pictures/thumbs_6/sample/00000000-full.jpg"],"tags": ["NEW"],"dateListed": "2026-01-01","description": "Sample listing description.","scrapedAt": "2026-01-01T00:00:00.000Z"}
Output views
The dataset has three views in the Console: Overview (price, address, size, status and agent for every record), Detail (price and tax history, features, open houses and agent contact; filled when Fetch property details is on) and Changes (changeType, changedFields and first/last seen; filled in Incremental mode).
Pricing
You pay per listing returned. When Fetch property details is on, an additional detail-enrichment event is charged once per returned listing that actually carries detail data. A compact UPDATED or EXPIRED row, a listing suppressed as unchanged or duplicated, and a failed fetch are never charged. The Pricing tab shows the current rates; Max items caps the spend of any run.
Plan Requirement
Datacenter and residential connections both work, but neither is guaranteed on every request. In our measurements the site checks the connection first and then refuses some exits at random: search pages and /home/ pages loaded over the default Apify datacenter connection pinned to the United States, /building/ pages were refused on datacenter exits and loaded over Apify Residential, and a residential exit was itself refused on some tries. The actor therefore reads search and home pages on the default connection, switches to Apify Residential for building pages, and retries on other exits before giving up, so you do not need to pick anything for a normal run. Apify free plans do not include Apify proxy, so on a free plan the actor can only use your own proxy URLs or its backup connection. If the selected connection is unavailable, the log shows:
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. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.
and, once a page is served that way: "Served over the backup connection (the default connection was unavailable)."
If no page can be read at all, the run ends as failed with one of these reasons:
- "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: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."
- "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 Trulia pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- "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."
Behaviour change: the default used to be Residential (US); runs whose saved input already selects Residential are unchanged. Proxy traffic is billed to your Apify account.
FAQ
How much does it cost?
See the Pricing section above for what is charged and when; the Pricing tab shows the current rates.
Is it legal to scrape Trulia?
This actor collects only publicly available real estate listing data. You are responsible for how you use it: follow Trulia's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts (price, address, specs) are generally factual data, but photos and some agent/broker content 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 with the same search or URL input and turn on Incremental mode. Each run then returns only new, updated and reappeared listings, and unchanged ones are not billed.
Why did my run return fewer listings than I expected?
The most common reason is Max items: raise it, or set it to 0 for unlimited, to walk every available result page. Max pages is a separate, optional cap on pages per search or URL; leave it empty to remove it. A search or keyword that is genuinely narrow can also just have few results on Trulia itself.
Why is a listing sometimes missing even though it is on Trulia?
Two common causes. First, the selected connection may be refused by the site on some exits; try again or select Apify Residential (US). Second, in URL mode with several overlapping URLs, when one URL's share of Max items ends partway through a results page, the uncollected listings on that page are still treated as already seen for the rest of the run. If another URL in the same run reaches one of them, it is skipped without a warning rather than returned. Set Max items to 0 and use Max pages as the bound, or run overlapping URLs as separate runs, to avoid it. A run continued after a platform migration or Resurrect can also miss a few listings from the page in progress at that moment; a follow-up run with Resume pointed at it collects them.
Why did my run fail instead of returning an empty dataset?
If nothing could be read at all (for example, every request was refused), the run stops with a clear message so "no listings match" is never confused with "nothing could be read." Run it again in a few minutes, and if it keeps happening, select Apify Residential (US) in the Proxy & connection field.
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:
| ๐งฉ Homes.com Scraper Scrape US property records from Homes.com. Pick a city, state or ZIP and a channel (for... | ๐ Redfin Scraper Scrape redfin.com home listings: price, beds, baths, sqft, lot, year built, coordinates... |
| ๐ Zumper Scraper Scrape Zumper.com rental listings: apartments, houses, condos and rooms. Pulls 60+ fields... | ๐ Realtor.com Extract property listings from realtor.com. Get comprehensive data, including prices... |
| ๐ Realtor.ca Scrape Realtor.ca property listings with prices, descriptions, images, agent and... | ๐งฉ Zillow Scraper Scrape zillow.com properties for sale, for rent and recently sold across the US: price... |
๐ Browse all abotapi scrapers
๐ฌ Support
- ๐ Found a bug or a missing field? Open a ticket on the Issues tab. 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.