US Distressed Property Scraper icon

US Distressed Property Scraper

Scrape US distressed property leads from Socrata open data across Chicago, New York, Seattle and New Orleans. Extract building violations, vacant…

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

US Distressed Property Scraper at a glance

US Distressed Property Scraper is a ready-to-run Apify actor from abotapi for collecting real estate data. Its documented output includes record id, country, source, title and distress type, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $2.40 per 1,000 results on the Apify Free plan and from $1.80 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Real Estate, Automation, Developer Tools
Region
North America
Pricing
$2.40 per 1,000 results (Free plan), from $1.80 on paid plans
Output
Documented below · JSON, CSV, Excel
Inputs
22 options

Scrape US distressed property leads from Socrata open data across Chicago, New York, Seattle and New Orleans. Extract building violations, vacant properties, tax sales and foreclosure records. Supports resume and incremental change tracking for ongoing property monitoring.

What US Distressed Property Scraper can do

  • Four metros, one actor. Walk Chicago building violations, vacant buildings and Cook County tax sales; New York building, housing and ECB violations plus tax-lien sales; King County foreclosure parcels; New Orleans sheriff lien-foreclosure sales. Every record comes back normalized to one schema.
  • Signal-level rows. Each violation, lien and sale row is its own record with native identity, dates, status, parties where published, fines and balances - the same granularity distress buyers work with.
  • Open data, no walls. Every lane reads the municipalities' own public JSON APIs at a polite pace, most recent first, with an optional recency cutoff.
  • Made for recurring monitoring. Resume an interrupted run from its ID, or let incremental mode remember what you already scraped and return only NEW and UPDATED records, with EXPIRED markers when a record leaves the source.
  • Search by metro or paste links. Walk whole metros, override with any Socrata dataset id, or paste Socrata API links and let URL mode sort them out.
  • Honest by design. If a source refuses every request the run fails loudly instead of returning an empty dataset that looks like "no results". A genuine empty search says so.

Choose what to collect

These inputs let you configure US Distressed Property Scraper - Violations & Foreclosures. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestringHow to discover records. 'search' walks the selected metros (or the dataset override) with your filters. 'url' reads only the links you paste into urls. Pasted links are ignored in search mode; the run log tells you when that happens.

Choices: search, url

metrosarrayWhich metro registers to walk, in order. Chicago = building violations, vacant buildings and Cook County tax sales. NYC = building, housing and ECB violations plus tax-lien sales. Seattle = King County foreclosure parcels. New Orleans = sheriff lien-foreclosure sales. Empty = all four metros.
datasetIdstringWalk exactly one Socrata dataset id (e.g. 22u3-xenr) instead of the metro lists. Pair with Dataset domain when it lives outside New York.
datasetDomainstringSocrata domain for the dataset override, e.g. data.cityofchicago.org.
sinceDaysintegerDate-filtered datasets return only rows newer than this many days ago. 0 = no cutoff (walk from the newest row). Small sets (foreclosures, tax sales) ignore fine cutoffs and walk whole.
soqlWherestringOptional raw SoQL $where clause, ANDed with every walked dataset's own filter, e.g. violation_status = 'OPEN'. Column names are dataset-specific, so with several metros pick a dataset override or a single metro.
dateFromstringAbsolute start of the date window on each dataset's date column. Replaces 'newer than N days' when set. Undated datasets (King County foreclosures) ignore it.
Show 15 more inputs
More input fields
InputWhat it controls
dateTostringAbsolute end of the date window (inclusive). Undated datasets ignore it.
sortOrderstringWhich end of each dataset to walk first: newest rows first (default) or oldest rows first.

Choices: newest, oldest

maxItemsPerDatasetintegerStop each dataset after this many rows, so one big register cannot use up Max items. 0 = no per-dataset cap.
urlsarrayPasted Socrata links: the API resource (https:///resource/.json or .csv), the dataset page (/d/, /dataset//) or the legacy /api/views//rows.json. Pasted $order, $where, $offset and $limit are honoured. Each link is walked as its own scope. Read in url mode only. The field is pre-filled with one example of every supported shape, so URL mode with the field untouched scrapes those examples.
maxItemsintegerStop after this many results total across all metros. Default 50; 0 = no limit (a wide metro can hold hundreds of thousands of rows, so set a number you are happy to pay for).
maxPagesintegerStop each dataset walk after this many API pages. 0 = walk until the natural end. Max items always applies too.
resumeFromRunIdstringContinue a previous run: only records not already in that run’s dataset are pushed. Leave empty for a fresh run.
incrementalModebooleanTrack records across scheduled runs with the same scope: only NEW or UPDATED records are returned (UNCHANGED suppressed), and records that disappear are marked EXPIRED. Mutually exclusive with Resume.
emitUnchangedbooleanIn incremental mode, also return records that did not change (marked UNCHANGED).
emitExpiredbooleanIn incremental mode, also return records seen previously that no longer appear (marked EXPIRED).
stateKeystringName for the incremental baseline when you want to share one baseline across different filter variants. Leave empty to derive it from the scope automatically.
ignoreFieldsForChangesarrayAdvanced: record fields that should never count as a change (in addition to the built-in ignore list). Example: ["status"].
mcpConnectorsarrayOptionally send a summary of each returned property to connected apps. Authorize a connector under Apify > Settings > Integrations, then select it here. Notion creates a page per record; other connectors receive a best-effort write or digest. Leave empty to skip. Dataset results are unaffected.
notionParentPageUrlstringURL or ID of the Notion page where record pages should be created. Required for Notion; ignored by other connectors.
maxNotifyListingsintegerMaximum number of records written to each connector. Does not affect dataset output.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

recordIdRecord ID (text)
countryCountry (text)
sourceSource (text)
titleTitle (text)
distressTypeDistress type (text)
portalIdSource row ID (text)
publishedAtPublished (date)
auctionDateAuction / sale date (date)
locationLocation (text)
valueAmountValue (number)
valueCurrencyCCY (text)
valueTextValue (text) (text)
Show 16 more fields
statusStatus (text)
urlURL (link)
changeTypeChange (incremental mode) (text)
firstSeenAtFirst seen (date)
lastSeenAtLast seen (date)
sourceDomainPortal (text)
datasetIdDataset ID (text)
sourceRecordIdSource record ID (text)
streetNumberStreet no. (text)
streetNameStreet (text)
cityCity (text)
stateState (text)
postalCodeZIP (text)
latitudeLatitude (number)
longitudeLongitude (number)
changedFieldsChanged fields (text)

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "recordId": "us:socrata:22u3-xenr:7000000",
  "country": "us",
  "source": "chicago-violations",
  "title": "123 Sample St MAINTAIN WINDOW",
  "distressType": "violation",
  "portalId": "7000000",
  "publishedAt": "2026-10-09T00:00:00.000",
  "location": {
    "address": "123 Sample St",
    "city": "Chicago",
    "region": "IL",
    "country": "US"
  },
  "valueAmount": 2500,
  "valueCurrency": "USD",
  "valueText": "$2,500",
  "status": "OPEN",
  "description": "MAINTAIN WINDOW Failed to maintain windows in sound condition and good repair.",
  "details": {
    "dataset": "22u3-xenr",
    "metro": "chicago",
    "lat": 41.73,
    "lng": -87.61,
    "violation_code": "CN000000",
    "inspection_number": "14000000",
    "inspection_status": "FAILED"
  },
  "url": "https://data.cityofchicago.org/resource/22u3-xenr.json",
  "raw": {}
}

Ways to use this data

  • Who: Investors and buyers hunting below-market property across US code-enforcement and tax-sale channels.
  • Who: Compliance and risk teams monitoring building violations and vacant stock by metro on a schedule.
  • Who: Lead-generation teams feeding distressed-property signals into CRM systems and alerting pipelines.
  • Who: Analysts comparing municipal distress volumes across Chicago, New York, Seattle and New Orleans from one dataset.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does US Distressed Property Scraper return?

The documented output for US Distressed Property Scraper includes record id, country, source, title, distress type, source row id, published and auction / sale date. Availability of each field depends on the source page and the selected mode.

How much does US Distressed Property Scraper cost?

It costs $2.40 per 1,000 results on the Apify Free plan and from $1.80 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Can I get only new or changed records on a schedule?

Yes. Use incremental mode: the actor remembers its baseline per scope and returns only what changed (NEW, UPDATED), with optional EXPIRED markers for records that left the source. Use stateKey to share one baseline across slightly different filter variants.

Why does a run return fewer records than I expected?

Max items (50 by default) stops the run once the cap is reached, walking the selected metros in order; raise it or set it to 0 to collect everything. The recency cutoff (sinceDays) also hides older rows on date-filtered datasets; raise it or set it to 0 for the full history.

How current is each source?

Chicago violations, New York housing, building and ECB violations are updated daily. Chicago vacant buildings and New York tax-lien sales are updated a few times a year, so a short recency cutoff can return nothing for them. The Cook County tax-sale lists (last sale year 2014 and 2015) and the New Orleans sheriff lien-foreclosure sales (cases up to 2018) are historical archives their cities no longer update, and the King County foreclosure list holds parcel numbers only, with no address or date. Use a larger recency cutoff, or 0, to see them.

Can I use it with AI agents or MCP?

Yes, the run output is a clean JSON dataset that works with MCP connectors and any AI workflow. Use the mcpConnectors input to send results straight into your apps after each run.

Ready to collect with US Distressed Property Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.