PublicGIS API

Parcel facts with their sources

Look up a parcel by address, point or county and parcel number, then read its facts by section: basics, assessment, tax, sales, zoning and overlays. Every fact names its source, source URL, retrieved date and license class. Official government pages for the parcel come from GISFinder. This is built for one parcel or one question at a time, not for bulk export.

Rules

Quickstart

No key is needed to start. Find the parcel:

curl 'https://api.publicgis.com/v1/parcels/lookup?address=123+Main+St+Springfield+MN'

Take a parcel_uid from the candidates and read its facts, or just the sections you need:

curl 'https://api.publicgis.com/v1/parcels/pg_01J9ZX3T5C8E2D7Q4W6B1N0MRA?sections=basics,assessment'
curl 'https://api.publicgis.com/v1/parcels/pg_01J9ZX3T5C8E2D7Q4W6B1N0MRA/overlays'
curl 'https://api.publicgis.com/v1/parcels/pg_01J9ZX3T5C8E2D7Q4W6B1N0MRA/official-resources?topic=assessor'

Parcels in a small area, filtered by acreage or land use:

curl 'https://api.publicgis.com/v1/parcels?lat=46.1005&lon=-93.0995&radius_m=500&min_acres=5'

With a key, send it as a bearer token:

curl -H 'Authorization: Bearer pgk_...' 'https://api.publicgis.com/v1/parcels/lookup?lat=46.1005&lon=-93.0995'

Every answer is the envelope data, sources, as_of, request_id, notices. Errors are RFC 9457 application/problem+json. Coordinates are WGS84, longitude first.

Keys

Without a key you are limited per IP address to 60 requests a minute and 1000 a day. With a key: 300 a minute and 20000 a day. A key is shown once and stored only as a digest; keep it on your server, never in browser code.

Get a key

Sign-up is not open yet. It opens with the API.

Limits, caching and CORS

Errors

The type of every problem is https://www.publicgis.com/problems/ followed by one of: invalid-request ◦ invalid-key ◦ not-found ◦ no-match ◦ license-not-cleared ◦ method-not-allowed ◦ rate-limited ◦ not-yet-open ◦ unavailable ◦ server-error.

Versions and deprecation

This is version 1 under /v1. New fields and endpoints may be added at any time; ignore what you do not know. An endpoint, parameter or field is removed no sooner than 12 months after it is announced in the changelog, and deprecated responses carry Deprecation and Sunset headers.

MCP server for AI agents

The same data is offered to AI agents at https://api.publicgis.com/mcp (Streamable HTTP, read-only tools find_parcel, get_parcel_report, check_parcel_overlays, find_parcels_in_area, get_official_resources, get_coverage). See llms.txt.

Reference

Generated from the OpenAPI 3.1 document, which is the source of truth.

GET /v1/parcels/lookup

Up to five parcel candidates for an address, a point, or a county and APN. Give exactly one of address; lat and lon; or county_geoid and apn. An address is matched only against the parcel's own site address, city, ZIP and county, never owner names, so this is not a person search.

ParameterInTypeNotes
addressquerystringA street address, for example 123 Main St Springfield MN
latquerynumberWGS84 latitude
lonquerynumberWGS84 longitude
county_geoidquerystringFive-digit county GEOID, with or without the county: prefix
apnquerystringThe county's parcel number as published

GET /v1/parcels/{parcel_uid}

Facts for one parcel by section, each with its sources and as_of date. A retired parcel_uid answers with status superseded and the live successors. A parcel that is hidden, suppressed or protected answers 404; delete any copy you hold.

ParameterInTypeNotes
parcel_uid (required)pathParcelUid
sectionsquerystringComma-separated subset of basics, assessment, tax, sales, zoning, overlays. Default all.
geometryqueryone of simplified, full, noneGeoJSON outline in basics, simplified to about a metre by default.

GET /v1/parcels/{parcel_uid}/overlays

Flood zones, wetlands and soils as shares of the parcel's mapped area. Screening from mapped layers, not an official flood determination or wetland delineation. FEMA's flood layer covers most but not all of the country; an empty flood list where no FEMA layer exists is not a finding of no flood risk.

ParameterInTypeNotes
parcel_uid (required)pathParcelUid

GET /v1/parcels/{parcel_uid}/official-resources

Official government resources for the parcel's place, from GISFinder. Ranked official pages for one topic from GISFinder's directory (www.gisfinder.com), for the smallest jurisdiction containing the parcel and then its county and state, each with GISFinder's verification status. This is GISFinder's compilation, not PublicGIS data. Answers 503 unavailable when GISFinder cannot be reached.

ParameterInTypeNotes
parcel_uid (required)pathParcelUid
topic (required)queryTopic

GET /v1/parcels

Parcels in a small box or circle, filtered by acreage and land use. Give bbox, or lat, lon and radius_m. The box may cover at most 2 square kilometres and the radius at most 1000 metres. At most 50 parcels per page, in a stable order; pass next_cursor as cursor for the next page with the same query. Never returns owner names or mailing addresses, at any tier.

ParameterInTypeNotes
bboxquerystringmin_lon,min_lat,max_lon,max_lat in WGS84
latquerynumber
lonquerynumber
radius_mquerynumber
min_acresquerynumber
max_acresquerynumber
land_usequerystringCase-insensitive text found in the county's land use class
limitqueryinteger
cursorquerystring

GET /v1/coverage

Which counties the API serves and how fresh they are. Without jurisdiction_id, every county served through the API (license cleared), optionally for one state. With jurisdiction_id, whether PublicGIS shows that jurisdiction on the web and whether it is cleared for the API.

ParameterInTypeNotes
statequerystringTwo-letter postal code
jurisdiction_idquerystring

Schemas

LicenseClass one of open, public_record, restricted_no_redistribution, licensed_third_party, unknown
ParcelUid string

Opaque, stable parcel id (pg_ and a ULID). It survives re-imports; a split or merged parcel's old id answers superseded.

JurisdictionId string
Topic one of parcel_map, county_gis, assessor, property_tax_payment, tax_collector, recorder_deeds, plats_surveys, zoning, building_permits, septic_well, wetlands, floodplain, soils, elevation, roads_right_of_way, public_land, property_records_general

GISFinder's topic vocabulary (platform contract 4.3)

Instant string or null

ISO 8601, a UTC date-time ending in Z or a calendar date

Value string or number or boolean or null or array or object

A published value, as the source gives it

Text string or null
Number number or null
Geometry object

GeoJSON, WGS84, longitude first

typeone of Point, Polygon, MultiPolygon
coordinatesarray
Source object
idstring
namestring
urlstring or null
publisherstring
officialboolean
retrieved_atInstant
license_classLicenseClass
as_ofInstant
Envelope object
dataany
sourcesarray of Source
as_ofInstant
request_idstring
noticesarray of stringPlain-language caveats, always including that parcel maps are not surveys and the FCRA ban
Candidate object
parcel_uidParcelUid
publicgis_urlstring
jurisdiction_idstring
county_namestring
statestring or null
apnstring
confidencenumber
matched_byone of address, point, apn
situs_addressText
situs_cityText
situs_zipText
LookupEnvelope object
dataobject
SectionStatus one of ok, empty, not_cleared, unavailable

ok; empty (nothing published); not_cleared (a source exists but its license does not allow the API); unavailable (try again later)

Section object
statusSectionStatus
as_ofInstant
sourcesarray of Source
factsobject
BasicsFacts object

owner_name, taxpayer_name and both mailing addresses appear only for a key whose holder accepted the current API Terms, and only where the county's parcel and owner sources are cleared, allow reuse of person fields and the state policy allows them. Never without a key.

apnValue
owner_nameValue
taxpayer_nameValue
owner_mailing_addressValue
taxpayer_mailing_addressValue
situs_house_numberValue
situs_addressValue
situs_cityValue
situs_zipValue
municipalityValue
plss_townshipValue
plss_township_directionValue
plss_rangeValue
plss_range_directionValue
plss_sectionValue
acres_reportedValue
deeded_acresValue
legal_descriptionValue
platValue
lake_nameValue
land_use_classValue
land_use_class_2Value
land_use_class_3Value
school_districtValue
tax_districtValue
year_builtValue
bedroomsValue
bathroomsValue
living_sqftValue
building_sqftValue
acres_mappedValue
geometryGeometry
centerGeometry
AssessmentRecord object
land_valueValue
noteValue
improvement_valueValue
assessment_yearValue
market_valueValue
assessed_valueValue
classValue
cardValue
taxable_valueValue
roll_stageValue
school_assessed_valueValue
school_taxable_valueValue
year_builtValue
living_sqftValue
residential_unitsValue
buildingsValue
forest_law_valueValue
tax_yearValue
use_codeValue
auxiliary_classValue
deeded_acresValue
tillable_acresValue
pay_yearValue
tax_capacityValue
site_valueValue
dwelling_valueValue
equalized_valueValue
classesValue
source_idValue
last_publishedValue
TaxRecord object

Balances, penalties, payment and delinquency status are never served by the API.

tax_yearValue
noteValue
derived_fieldsValue
net_taxValue
gross_taxValue
tax_totalValue
first_half_taxValue
second_half_taxValue
installment_1_amountValue
installment_2_amountValue
special_assessmentsValue
classValue
prior_year_totalValue
source_idValue
last_publishedValue
SaleRecord object

Flags that describe the buyer or seller (primary residence, related parties, gift or inheritance, distressed) are never served by the API. A multi-parcel sale price is the price of the whole transaction.

sale_dateValue
sale_monthValue
sale_priceValue
adjusted_priceValue
sale_price_kindValue
value_at_saleValue
ratioValue
qualifiedValue
qualification_codeValue
reject_reasonValue
instrumentValue
documentValue
bookValue
pageValue
recorded_dateValue
deed_typeValue
sale_typeValue
statusValue
class_codeValue
property_classValue
property_typeValue
multi_parcelValue
multi_parcel_codeValue
improvedValue
jurisdictionValue
deeded_acresValue
year_builtValue
study_yearValue
noteValue
ecrvValue
ecrv_idValue
certificate_stageValue
net_amountValue
personal_propertyValue
partial_interestValue
government_saleValue
new_constructionValue
split_or_combinedValue
includedValue
planned_useValue
prior_useValue
source_idValue
last_publishedValue
rejectedValue
sale_yearValue
tillable_acresValue
transaction_parcelsValue
AssessmentFacts object
assessment_yearValue
land_valueValue
building_valueValue
total_valueValue
market_valueValue
value_kindValue
assessed_valueValue
assessed_kindValue
assessed_yearValue
recordsarray of AssessmentRecord
TaxFacts object
recordsarray of TaxRecord
SalesFacts object
last_sale_priceValue
last_sale_dateValue
sale_price_kindValue
recordsarray of SaleRecord
ZoningFacts object
zoningarray of object
land_usearray of object
OverlayFacts object

Shares of the parcel's mapped area, in percent. Screening only.

floodarray of object
wetlandsarray of object
soilsarray of object
OverlaySection object
factsOverlayFacts
Sections object
basicsany
assessmentany
taxany
salesany
zoningany
overlaysOverlaySection
ParcelHead object
parcel_uidParcelUid
statuscurrent
publicgis_urlstring
jurisdiction_idstring
county_namestring
statestring or null
apnstring
ParcelReport object
sectionsSections
ParcelOverlays object
overlaysOverlaySection
SupersededParcel object
parcel_uidParcelUid
statussuperseded
superseded_byarray of ParcelUid
publicgis_urlstring
ParcelEnvelope object
dataParcelReport or SupersededParcel
OverlaysEnvelope object
dataParcelOverlays or SupersededParcel
Resource object

One official page from GISFinder's directory, with GISFinder's verification status

resource_idText
namestring
descriptionText
urlstring
topicsarray of string
jurisdiction_idText
publisherText
officialboolean
verified_statusone of verified, not_yet_verified, possibly_broken, None
verified_atInstant
license_classLicenseClass
page_urlstring or null
OfficialResources object
parcel_uidParcelUid
jurisdiction_idstring
topicTopic
providerGISFinder
placeobject or nullThe smallest jurisdiction GISFinder resolved for the parcel's point
resourcesarray of Resource
ResourcesEnvelope object
dataOfficialResources or SupersededParcel
AreaParcel object

A parcel summary. Never carries owner names or mailing addresses.

parcel_uidParcelUid
publicgis_urlstring
jurisdiction_idstring
county_namestring
statestring or null
apnstring
acres_reportedValue
acres_mappedValue
land_use_classValue
land_use_class_2Value
land_use_class_3Value
situs_addressValue
situs_cityValue
situs_zipValue
centerGeometry
AreaResult object
countintegerParcels matching the whole query
parcelsarray of AreaParcel
next_cursorstring or null
AreaEnvelope object
dataAreaResult
CountyCoverage object
jurisdiction_idstring
county_namestring
statestring or null
web_coveredboolean
api_clearedbooleanThe county's parcel source is licensed open or public_record, so the API serves it
sourceSource or null
as_ofInstant
AreaCoverage object
jurisdiction_idstring
namestring
web_coveredboolean
api_clearedboolean
countiesarray of CountyCoverage
as_ofInstant
ServedCoverage object
statestring or null
countinteger
countiesarray of CountyCoverage
CoverageEnvelope object
dataServedCoverage or CountyCoverage or AreaCoverage
Problem object

RFC 9457. type is one of https://www.publicgis.com/problems/ invalid-request, invalid-key, not-found, no-match, license-not-cleared, method-not-allowed, rate-limited, not-yet-open, unavailable, server-error.

typeone of https://www.publicgis.com/problems/invalid-request, https://www.publicgis.com/problems/invalid-key, https://www.publicgis.com/problems/not-found, https://www.publicgis.com/problems/no-match, https://www.publicgis.com/problems/license-not-cleared, https://www.publicgis.com/problems/method-not-allowed, https://www.publicgis.com/problems/rate-limited, https://www.publicgis.com/problems/not-yet-open, https://www.publicgis.com/problems/unavailable, https://www.publicgis.com/problems/server-error
titlestring
statusinteger
detailstring
instancestring
request_idstring
coverageCountyCoverage or null