VOOZH about

URL: https://apify.com/shelvick/county-property-records

⇱ County Property Records API β€” Owner, Value, Tax & Sales Β· Apify


πŸ‘ County Property Records API β€” Owner, Value, Tax & Assessor Data avatar

County Property Records API β€” Owner, Value, Tax & Assessor Data

Pricing

from $42.50 / 1,000 property record resolveds

Go to Apify Store

County Property Records API β€” Owner, Value, Tax & Assessor Data

County property records by address or parcel ID β€” a property owner lookup by address returning owner, assessed and market value, property tax history, and sale history, normalized into one schema across many US counties from public assessor and recorder data. For agents, not consumer listings.

Pricing

from $42.50 / 1,000 property record resolveds

Rating

0.0

(0)

Developer

πŸ‘ Scott Helvick

Scott Helvick

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

4

Monthly active users

3 days ago

Last modified

Share

County Property Records API β€” Owner, Value, Tax & Sales

County property records are public, but scattered across thousands of county assessor and recorder sites, each with its own portal, format, and quirks. This Actor is a county property-records API: do a property owner lookup by address (or pass a parcel ID) and get a normalized property record β€” owner, assessed value, market value, property tax history, and sale history β€” sourced from public county assessor and recorder data, in one schema across many counties, so an agent calls one tool instead of learning a new site per county.

What this does

  • Address β†’ property record. Pass full street addresses; each is routed to its county and returned as one normalized record.
  • Parcel ID β†’ property record. Already have the assessor parcel/account number? Pass STATE/County/ParcelID for an exact lookup.
  • One unified schema across counties. Every record has the same shape regardless of which county it came from: owner_name, parcel_id, assessed_value, market_value, tax_year, tax_history, last_sale_date / last_sale_price, sale_history, and characteristics (year built, building/lot area, units).
  • Public-record sourcing. Data comes from county assessor/recorder offices and government open-data β€” public records you're allowed to use and resell β€” not from consumer real-estate listing portals.
  • Batch + pay-on-success. Submit many lookups in one run; you're charged only for records actually resolved. Counties not yet covered, and lookups that don't resolve, are returned with a status and are never charged.
  • Live coverage manifest. Every successful run writes the current supported-county list to its key-value store under COVERAGE, so you can read the exact covered set straight from any run rather than trusting a static list (see Calling from an AI agent).

Use cases:

  • Enrich a list of addresses with owner, value, and last-sale data for diligence or lead research.
  • Pull assessed value + sale history for a specific parcel during underwriting.
  • Build a property dataset across several metros from one agent-callable tool.
  • Verify owner-of-record and tax-year valuation for a known parcel ID.

Why one schema across counties matters

The hard part of property data isn't any single county β€” it's that every county publishes differently. A scraper built for one county is a commodity: it solves 1/3000th of the problem and breaks on its own when that county redesigns its site. The moment you need a second county you start over.

This Actor absorbs that heterogeneity behind a single contract. Internally each county has its own source β€” a clean government open-data API where one exists, a rendered public portal where it doesn't β€” but the output is identical across all of them. Coverage grows over time without changing the call you make or the shape you parse.

Field coverage is best-effort per county: every record uses the same schema, with null where a particular county doesn't publish a particular field (one county may expose full sale history but not building characteristics; another the reverse). The contract is stable; the fill rate depends on what each county makes public. That's an honest tradeoff, surfaced in the data rather than hidden.

How it compares

ApproachMultiple counties, one schemaPublic-record sourcedPay-per-use, no minimumAgent-callable
Single-county scraperβ€”variesOKvaries
Enterprise property-data platformsOKOKβ€” (subscription + contract)β€”
US County Property RecordsOKOKOKOK

Single-county scrapers cover one place and leave you to stitch the rest together. Enterprise data platforms cover the country but gate it behind monthly minimums and sales contracts. This Actor sits in the open middle: many counties behind one schema, public-record data, billed per record with no commitment, callable directly by an agent.

Input

FieldTypeRequiredDefaultDescription
addressesarray of stringsone of[]Full US property street addresses, e.g. "1001 Preston St, Houston, TX 77002". Each is matched to its county and returned as one record. Include city + state (and ZIP if known) for reliable routing.
parcelLookupsarray of stringsone of[]Direct parcel/account lookups as STATE/County/ParcelID, e.g. "IL/Cook/15362060520000". Use when you already know the ID.
countystringno--Optional county hint (without "County"), e.g. "Cook", to disambiguate addresses across county lines.
statestringno--Optional two-letter state code, e.g. "IL", paired with county.
includeHistorybooleannotrueInclude full tax-year and recorded-sale history where the county publishes it. Set false for a current-snapshot-only record (faster, smaller).
maxRecordsintegerno50Safety cap on records resolved per run (1–1000).

Provide addresses, parcelLookups, or both β€” at least one is required.

Output

One dataset record per lookup. Example (completed):

{
"query":"425 Addison Rd, Riverside, IL 60546",
"query_type":"address",
"status":"completed",
"county":"Cook",
"state":"IL",
"parcel_id":"15362060520000",
"owner_name":"SMITH JOHN A & JANE B",
"situs_address":"425 ADDISON RD, RIVERSIDE, IL 60546",
"mailing_address":"425 ADDISON RD, RIVERSIDE, IL 60546",
"assessed_value":37000,
"market_value":null,
"land_value":14350,
"improvement_value":22650,
"tax_year":2025,
"tax_history":[],
"last_sale_date":"2018-04-20",
"last_sale_price":249000,
"sale_history":[
{"date":"2018-04-20","price":249000,"document_type":"Warranty","doc_number":"1815701295"}
],
"characteristics":{"year_built":1998,"building_sqft":2450},
"source_url":"https://www.cookcountyassessor.com/pin/15362060520000",
"fetched_at":"2026-06-22T14:03:11Z",
"error":null,
"field_notes":[]
}

status is one of completed, not_covered (county not yet supported), or failed (covered county, no match β€” see error). Nullable fields are null where the county doesn't publish them. Every field is described in the dataset schema.

When a field is absent for a structural reason, field_notes explains it β€” and distinguishes data that's omitted by law (not part of the public record β€” e.g. sale prices in Texas, a non-disclosure state) from data that's simply not in that county's source (public elsewhere, not yet wired in). For example, a Texas record carries {"fields": ["last_sale_price", "last_sale_date", "sale_history"], "reason": "omitted_by_law", "detail": "Texas is a non-disclosure state β€” sale prices are not part of the public record."}. An empty array means everything was sourced normally.

Example

{"addresses":["1060 Wakeling St, Philadelphia, PA 19124"],"includeHistory":true}
curl-X POST "https://api.apify.com/v2/acts/shelvick~county-property-records/run-sync-get-dataset-items?token=YOUR_TOKEN"\
-H"Content-Type: application/json"\
-d'{"addresses":["1060 Wakeling St, Philadelphia, PA 19124"],"includeHistory":true}'
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("shelvick/county-property-records").call(
run_input={"addresses":["1060 Wakeling St, Philadelphia, PA 19124"]}
)
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
print(record["owner_name"], record["assessed_value"], record["last_sale_price"])

Calling from an AI agent

Apify MCP server (mcp.apify.com). This Actor is exposed as a callable tool; the input schema is self-documenting, so an LLM can construct correct calls from the tool description alone. Pass an address (or a STATE/County/ParcelID) and read back a normalized property record. Pay per call via x402 USDC on Base or Skyfire managed tokens β€” this Actor is enabled for agentic payments.

Apify SDK (Python). See the example above (apify_client).

REST API. Use run-sync-get-dataset-items for small synchronous batches; the async /runs endpoint for larger ones.

Checking which counties are covered. Every successful run writes the live supported-county list to its default key-value store under the COVERAGE key, shaped {"counties": [{"state": "TX", "county": "harris"}, ...]} β€” state is the two-letter code and county is lowercase with no "county" suffix. Read it from a finished run's store (the run JSON carries defaultKeyValueStoreId):

run = client.actor("shelvick/county-property-records").call(run_input={"addresses":["..."]})
coverage = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("COVERAGE")
covered = coverage["value"]["counties"]# [{"state": "TX", "county": "harris"}, ...]
# STORE_ID = the run's defaultKeyValueStoreId
curl"https://api.apify.com/v2/key-value-stores/STORE_ID/records/COVERAGE?token=YOUR_TOKEN"

A not_covered result means that county isn't in the list yet; coverage only grows, so the same call starts returning data once it's added. (There's no separate pre-call coverage endpoint β€” read it from any recent run.)

Pricing

Pay-per-event, billed only on success: one charge per resolved property record, after the record is pushed. not_covered and failed results are returned for transparency but never charged, and a single Actor-start event is amortized across the whole batch. So a batch of addresses costs only for the ones that actually came back with data.

See the Pricing tab on this Store page for the current per-record rate and any active subscriber discounts.

Behavior

Run-level failures (rare): input validation only β€” at least one of addresses / parcelLookups must be present; maxRecords is 1–1000.

Per-record statuses (normal):

  • completed β€” record resolved and normalized.
  • not_covered β€” the county isn't supported yet (error: "county-not-covered"). Check the COVERAGE manifest for the current set.
  • failed β€” covered county but the lookup didn't resolve (error: "no-match", or a transient source error). Address matching is exact-ish; include city/state/ZIP for best results.

Performance: open-data counties resolve in roughly 1–3 s per record; counties served from a rendered portal, and the New York statewide layer, take longer (New York is ~10–20 s per lookup and may occasionally time out, returning a failed status you are not charged for). In very rural states (e.g. Montana) many parcels have no street address and resolve only by parcel ID; an address that finds no match returns failed and isn't charged. Lookups run concurrently, so a batch finishes far faster than the sum of its parts. Very large batches should use the async API rather than the 5-minute sync endpoint.

FAQ

Which counties are supported? A large, growing set spanning major metros across many states β€” plus fifteen whole states: Florida (all 67 counties), North Carolina (all 100 counties), Massachusetts (all 351 cities/towns, every county), Maryland (all 24 jurisdictions), New York (every county outside New York City), New Jersey (all 21 counties), Connecticut (all 169 towns / 8 counties), Montana (all 56 counties), Wisconsin (71 counties), Mississippi (all 82 counties), Arkansas (all 75 counties), Georgia (all 159 counties), Idaho (all 44 counties), Vermont (all 14 counties), and Maine (all 16 counties), each covered statewide. Marquee metros include Chicago (Cook), New York City, Philadelphia, Phoenix (Maricopa), Houston (Harris) and its suburbs (Fort Bend), Dallas–Fort Worth (Dallas/Tarrant/Collin/Denton/Johnson), San Antonio (Bexar), Austin (Travis) and the San Marcos corridor (Williamson/Hays/Bastrop), the northern Houston suburbs of Conroe and The Woodlands (Montgomery), the Rio Grande Valley β€” McAllen and Edinburg (Hidalgo), Brownsville and Harlingen (Cameron) β€” Longview and Beaumont-area Texas (Gregg/Orange) plus a growing set of other Texas appraisal districts, Atlanta (Fulton/Gwinnett/Cobb/DeKalb) plus all of Georgia statewide (Savannah, Augusta, Columbus, Macon, Athens), Miami (Miami-Dade), Tampa, Orlando, Jacksonville, Charlotte, Raleigh, Nashville and Chattanooga (Davidson and Hamilton) plus most of Tennessee statewide via the state Comptroller's assessment data (Clarksville, Kingsport, Johnson City, Jackson, Sevierville, Cleveland, and the long tail of counties β€” Knoxville, Memphis, and a few other large counties excepted), Cleveland, Columbus, Cincinnati (Hamilton), Akron (Summit), Toledo (Lucas), Canton (Stark), Lorain, the Cleveland east suburbs (Lake), Xenia/Dayton's Greene County, and the Columbus collar (Delaware, Licking, Fairfield), Detroit and its suburbs (Wayne, Oakland, Macomb), Las Vegas (Clark County) and Reno (Washoe), Seattle and Puget Sound (King and Snohomish), Vancouver (Clark County, WA), Pittsburgh (Allegheny) and the Philadelphia suburbs (Chester, Montgomery, Bucks), the Lehigh Valley (Northampton), Harrisburg's West Shore (Cumberland), Lancaster, and Reading (Berks), Denver and the Colorado Front Range (Jefferson, Arapahoe, Douglas, Weld, Adams, Boulder), Oklahoma City, Minneapolis–St. Paul and most of Minnesota by population (the Twin Cities metro plus Rochester, Duluth, St. Cloud, and the opt-in counties statewide), Milwaukee, St. Louis County, Kansas City (Jackson), Portland with its western suburbs and Salem (Multnomah, Washington, Marion), Tucson, Boston (Massachusetts), Baltimore/Washington suburbs (Maryland), upstate and Long Island New York (Buffalo, Rochester, Syracuse, Albany, Yonkers, Nassau/Suffolk), New Jersey statewide (Newark, Jersey City, and the Bergen–Essex–Hudson–Middlesex–Monmouth corridor), Connecticut statewide (Bridgeport, Stamford, New Haven, Hartford, Greenwich), Montana statewide (Billings, Missoula, Bozeman, Kalispell, Helena), Wisconsin statewide (Madison, Green Bay, Kenosha, Eau Claire, plus Milwaukee), Mississippi statewide (Jackson, Gulfport, Southaven, Hattiesburg, Biloxi), Florida statewide (Miami, Tampa, Orlando, Jacksonville, and all 67 counties), North Carolina statewide (Charlotte, Raleigh, Greensboro, Durham, and all 100 counties), Arkansas statewide (Little Rock, Fayetteville, Fort Smith, and all 75 counties), Idaho statewide (Boise, Meridian, Nampa, Coeur d'Alene, and all 44 counties), Albuquerque (Bernalillo), Birmingham (Jefferson), Greenville and Columbia (South Carolina), the Virginia coastal cities β€” Virginia Beach, Norfolk, Suffolk, and Williamsburg, Colorado Springs and the Colorado mountain counties (El Paso, Routt, Gunnison, La Plata, Grand, Huerfano), Norman, Stillwater, and Enid plus the Oklahoma City suburbs (Cleveland, Payne, Garfield, Canadian, McClain, Wagoner, Delaware), Bellingham, Yakima, the Tri-Cities, and Whidbey Island in Washington (Whatcom, Yakima, Benton, Island), Franklin and Brentwood south of Nashville (Williamson), Dover (Kent County, Delaware), Des Moines and Cedar Rapids (Polk and Linn, Iowa), Vermont statewide (Burlington, Montpelier, Rutland, Brattleboro, and all 14 counties), Maine statewide (Portland, Lewiston, Bangor, Augusta, and all 16 counties), Indianapolis (Marion), South Bend, Evansville, Lafayette, Bloomington, Elkhart, Valparaiso, and the southern-Indiana Louisville suburbs Jeffersonville and New Albany (Indiana), and major California metros β€” Los Angeles, San Diego, Orange County, San Francisco, Riverside, San Bernardino, Alameda, Sonoma, Contra Costa, and Ventura β€” with more added regularly. California, Maryland, and New Jersey records are returned without owner names (California redacts them by law; Maryland and New Jersey publish owner names through other county systems, not this statewide layer), as are a few individual counties whose public layer omits them (e.g. Seattle/King, Pittsburgh/Allegheny, and Oakland County, MI) β€” noted per record; Florida, North Carolina, New York, Connecticut, Montana, Wisconsin, Mississippi, Arkansas, Georgia, Idaho, Vermont, Maine, and Nevada (Las Vegas and Reno) records do include owner names, as do the metros added across Colorado, Ohio, Pennsylvania, Minnesota, Oregon, Washington, Missouri, Tennessee, New Mexico, Alabama, South Carolina, Oklahoma, Virginia, Delaware, Iowa, and Indiana; value, tax, characteristics, and parcel data are included throughout, and each record's field_notes explain any omission. The authoritative, always-current list is written to the COVERAGE key-value-store record on every run, so an agent can check coverage programmatically rather than trusting a static list.

What happens for a county you don't cover yet? You get a record with status: "not_covered" and you are not charged for it. Coverage expands over time; the same call will start returning data once that county is added.

Why is a field null? Counties publish different things. The schema is constant; a null means that county doesn't expose that field publicly. One county may have full sale history, another rich building characteristics β€” best-effort per source. Where there's a structural reason, field_notes on the record spells it out and separates omitted by law (e.g. Texas sale prices, California owner names β€” not part of the public record) from not in that county's source (public elsewhere, not yet wired in).

Am I charged for addresses that don't resolve? No. Only completed records are billed.

Can I look up by parcel number instead of address? Yes β€” pass STATE/County/ParcelID in parcelLookups for an exact lookup that skips address matching.

What this doesn't do

  • No consumer listing data. This returns official county assessor/recorder records, not for-sale listings, Zestimate-style estimates, or agent/MLS data.
  • No nationwide coverage (yet). It covers a curated, growing set of counties; uncovered counties return not_covered, not an error.
  • No owner contact info. Owner of record and mailing address come from public records; no phones, emails, or skip-tracing.
  • No fuzzy/owner-name search. Look up by address or parcel ID, not "all properties owned by X" β€” that 1β†’many shape isn't supported.
  • No guaranteed field completeness. Field fill rate varies by county (best-effort).

For for-sale listings and valuations, use a real-estate listings source. For nationwide enterprise coverage with SLAs, a subscription property-data platform is the better fit. For raw geometry/parcel boundaries, use a county GIS/parcel layer.


Design notes: www.scotthelvick.com/tools/county-property-records

You might also like

Property Price Tax History

coder_luffy/property-price-tax-history

Property price and tax history scraper that pulls records in bulk by property ID, listing URL, or address.

Property Tax Scraper

great_pistachio/property-tax-scraper

Search county property tax records and assessments β€” owner names, assessed values, tax amounts, sale history, and property details. Covers Miami-Dade (FL), Cook County (IL), and Maricopa County (AZ).

πŸ‘ User avatar

Saturnin Pugnet

29

Cook County Property Records Scraper | Real Estate Tax Data

parseforge/cook-county-property-records-scraper

Export Cook County, Illinois property tax and assessment records. Includes PIN, owner name, property address, tax year, assessed value, exemptions, and tax billed. Filter by tax year or PIN. Download as CSV, Excel, JSON, or XML. Sourced from Cook County open data.

Cook County Assessor's Property Scraper

parseforge/cookcountyassessor-scraper

Get Cook County property information in minutes. Search by address, area, or property number and receive clear details on property value, sales history, and key home features. Perfect for buyers, investors, and analysts who need reliable data to compare properties and make smarter decisions quickly.

Dallas Property Tax Scraper - Property Records API

pink_comic/dallas-county-property-tax-search

Scrape Dallas County property tax and appraisal records from DCAD/Dallas Tax Office. Search by owner, address, or account; export owner names, mailing addresses, values, tax levy, amount due, and legal descriptions for real estate leads, title, underwriting, and tax-lien research.