Web API

OGC web services (WMS, WFS, WMTS) and ArcGIS REST services for tile rendering and per-parcel attribute lookup.

The dataset is also made available to customers as OGC (WMS, WFS, etc) web services, and as ArcGIS REST services for ArcGIS Online, ArcGIS Pro and the ArcGIS SDKs.

Every data endpoint takes the API token issued after signup, either as Authorization: Bearer <TOKEN> or as a ?token=<TOKEN> query parameter. GetCapabilities, DescribeFeatureType and GetLegendGraphic are public and unmetered — they describe the service rather than return parcel data. Everything else except raster tiles counts against your plan; see Usage and limits.

Tile URL patterns

Two URL shapes serve the same tiles, and they differ in how they count rows:

Route y origin Use it from
https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@pbf/{z}/{x}/{y}.pbf XYZ, top-left QGIS, ArcGIS, Leaflet, OpenLayers, any plain XYZ client
https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@png8/{z}/{x}/{y}.png8 XYZ, top-left same
https://api.landrecords.us/pro/gwc/service/tms/1.0.0/pro:parcel_us@EPSG:3857x2@png8/{z}/{x}/{y}.png8 TMS, bottom-left clients configured for TMS (MapLibre scheme: 'tms')

Use plain {y} on both — there is no {-y} form. The route already decides the convention, so flipping y on top of it asks for a tile 2×|latitude| away, which is usually open water. When in doubt, use the bare (non-/gwc/service/tms/) paths: that is what our WMTS GetCapabilities advertises as its ResourceURL templates.

Tiles are also served under EPSG:900913 (EPSG:900913x2). There is no EPSG:4326 grid set, so connect with EPSG:3857 or EPSG:900913 only. All raster tiles are 512×512 px.

Fun fact: this is the same service that powers our data explorer! It is a MapLibre source configured like so:

yourAuthToken = ...;
map.current = new maplibregl.Map({
    style: {
        version: 8,
        sources: {
            parcel_us: {
                type: 'raster',
                scheme: 'tms',
                tiles: ['https://api.landrecords.us/pro/gwc/service/tms/1.0.0/pro:parcel_us@EPSG:3857x2@png8/{z}/{x}/{y}.png8'],
                tileSize: 512
            }
        }
    },
    transformRequest: (url, resourceType) => {
        if (resourceType === 'Tile' && url.startsWith('https://api.landrecords.us')) {
            return {
                url: url,
                headers: { 'Authorization': 'Bearer ' + yourAuthToken }
            }
        }
    }
});

Drop scheme: 'tms' and point the same source at the bare https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@png8/{z}/{x}/{y}.png8 path to get the identical tiles over the XYZ convention. For a vector source, use type: 'vector' with the @pbf path — parcel attributes travel inside the tile, so hover, highlight and labels resolve client-side with no round trip.

Vector tile attributes

Every parcel vector tile (@pbf) holds a single layer named parcels, with one polygon feature per parcel. Each feature carries the same 28 attributes at every zoom, from z10 to z16 (overscaled zooms reuse z16's features):

Attribute Type Description
lrid String Land Records' UUID for the parcel — the key for looking it up.
geoid String 5-digit county FIPS: statefp followed by countyfp.
statefp String State FIPS code.
countyfp String County FIPS code.
cousubfp String County subdivision FIPS code.
placefp String Census place FIPS code of the place containing the parcel's centroid; prefix statefp for the 7-digit place GEOID.
placetype String Type of place.
parceladdr String Physical street address.
parcelcity String City the parcel is in.
parcelstate String State the parcel is in.
ownername String Name of the recorded owner.
ownertype String Type of owner.
parceltype String Type of parcel.
accesstype String Type of access.
usecode String Land use code, as the county records it.
naicscode String North American Industry Classification System (NAICS) code.
zoningcode String Zoning code.
landvalue Number Assessed value of the land alone.
imprvalue Number Assessed value of improvements (buildings).
totalvalue Number Total assessed value.
calcarea Number Area of the parcel polygon, in square metres.
centroidx, centroidy Number Longitude and latitude of the parcel's geographic center (EPSG:4326). Can fall outside a C-shaped parcel.
surfpointx, surfpointy Number Longitude and latitude of a point guaranteed to lie inside the parcel — the one to put a label or marker on.
elevmin, elevavg, elevmax Number Minimum, average and maximum elevation across the parcel.

The full definitions are in the Table Schema. A few things to know when you read them out of a tile:

  • Empty attributes are left out, not sent as null. A parcel with no recorded zoning has no zoningcode key at all, so test for the key's presence.
  • Features have no vector-tile id. Use lrid as the identity — in MapLibre, set promoteId: 'lrid' on the source to drive feature-state hover and selection.
  • Everything else is one lookup away. Tiles carry this subset of the published attributes; parcelid, usedesc, yearbuilt, bldgsqft and the rest come back from a lookup by lrid.
  • Low-zoom tiles are heavy. Every parcel keeps every attribute down to z10, so a z10 tile over a dense metro runs to tens of megabytes. For display at low zooms, use the raster tiles and switch to vector around z14.
  • Canadian tiles (pro:parcel_ca, on api.landrecords.ca) carry the same layer without accesstype, elevmin/elevavg/elevmax, naicscode, ownertype, parceltype and placefp, and start at z12.
map.addSource('parcels', {
    type: 'vector',
    tiles: ['https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@pbf/{z}/{x}/{y}.pbf'],
    minzoom: 10,
    maxzoom: 16,
    promoteId: 'lrid'
});
map.addLayer({
    id: 'parcel-lines',
    type: 'line',
    source: 'parcels',
    'source-layer': 'parcels',
    paint: { 'line-color': '#2F7A2F', 'line-width': 0.5 }
});

Authenticate the source with the same transformRequest as the raster example above.

Parcel Coverage Map Service

We publish our coverage map as a web service for use in your applications. This is the same service that powers our public website at http://landrecords.us/products. It contains information about parcel coverage, as well as coverage for selected attributes.

  • County Coverages: https://api.landrecords.us/pro:county_coverage@EPSG:3857x2@pbf/{z}/{x}/{y}.pbf?token=<TOKEN>
  • State Coverages: https://api.landrecords.us/pro:state_coverage@EPSG:3857x2@pbf/{z}/{x}/{y}.pbf?token=<TOKEN>

Both coverage layers are vector-only, and both are also reachable over the TMS route (/pro/gwc/service/tms/1.0.0/…) with bottom-left rows.

QGIS: Configure in a WMS/WMTS Connection

You can easily load the Nationwide Parcel layer into QGIS.

First, Create a New WMS/WMTS Connection.

Then configure the new connection by pointing to the Landrecords API endpoint (api.landrecords.us), and setting the Authorization token provided after signup:

https://api.landrecords.us/pro/gwc/service/wmts

https://api.landrecords.us/pro/wms

Now you will see all the layers available to you in the Browser:

The WMTS document publishes pro:parcel_us, pro:state_coverage and pro:county_coverage over the EPSG:3857x2 and EPSG:900913x2 tile matrix sets, in both application/vnd.mapbox-vector-tile and image/png8.

QGIS: Configure in an XYZ / Vector Tiles Connection

Create a new XYZ Connection (for raster) or Vector Tiles Connection (for MVT):

Configure the connection with the Landrecords API endpoint. Use the standard {z}/{x}/{y} ordering — QGIS's {-y} flip is not wanted here, because these paths already serve top-left rows.

https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@pbf/{z}/{x}/{y}.pbf

https://api.landrecords.us/pro:parcel_us@EPSG:3857x2@png8/{z}/{x}/{y}.png8

Tile zoom ranges

The parcel layer has data from zoom 10 upward, for both vector and raster tiles (Canadian tiles from z12):

Layer Served zooms Notes
Raster (png8) z10–z22 Zoom <10 → 404 (nothing renders there). Above z16, tiles are re-rendered from their parent tile; high zooms (≥18) are rendered on demand and never persisted — they carry a 14-day browser cache header instead of being served as static objects, so they re-render across sessions.
Vector (pbf) native z10–z16, overscaled above Zoom >16 returns geometry scaled up from its parent tile; <10 → 404.

Requesting a zoom outside these ranges returns a 404, never an empty tile — a transparent tile is indistinguishable from correctly rendered empty ocean, and would hide a client-side coordinate bug behind pixels that look fine. Served tiles are cached 14 days and marked immutable; a 404/204 is cached only one hour.

Set the Authorization header to include the API key that was provided to you after signing up for the hosted web service.

Click Save, and now you’re ready to add this layer to your project.

ArcGIS REST services

The parcel layers are also published the way ArcGIS Server publishes a layer, so ArcGIS Online, ArcGIS Pro and the ArcGIS Maps SDK for JavaScript add them by URL like any other Esri service. The services directory is https://api.landrecords.us/arcgis/rest/services (the same services answer on api.landrecords.ca), and each country is published three ways:

Service URL Use it for
FeatureServer https://api.landrecords.us/arcgis/rest/services/parcel_us/FeatureServer Popups, attribute tables, filters and queries. Draws from about 1:18,000 (z15) in.
MapServer https://api.landrecords.us/arcgis/rest/services/parcel_us/MapServer Parcels at every scale as image tiles, plus export, identify and find.
VectorTileServer https://api.landrecords.us/arcgis/rest/services/parcel_us/VectorTileServer The vector tiles, styled as parcel outlines.

Use parcel_ca in place of parcel_us for Canadian parcels, on a plan that includes Canada. They are the same data, plans and meters as the OGC routes above, not a second copy.

Signing in

ArcGIS clients sign in through the server's token endpoint: enter any user name and your API key as the password. The token that comes back is your key, so there is no second credential to manage, and disabling the key ends every session made with it. Scripts can skip sign-in and pass token=<TOKEN>, Authorization: Bearer <TOKEN> or X-Esri-Authorization: Bearer <TOKEN>.

  • ArcGIS Online Map Viewer: Add → Add layer from URL, paste a service URL, and sign in when asked. Use the VectorTileServer or MapServer to show parcels at every scale and the FeatureServer for popups and the attribute table.
  • ArcGIS Pro: Insert → Connections → New ArcGIS Server, or Add Data From Path with a service URL. The feature layer needs ArcGIS Pro 3.2 or later, the first release that reads 64-bit object ids.
  • QGIS: Layer → Add Layer → Add ArcGIS REST Server Layer, with the directory URL and a Basic authentication (any user name, your key as the password). Use the MapServer or VectorTileServer: QGIS reads object ids as 32-bit, so for parcel features in QGIS use the WFS.

Querying the FeatureServer

FeatureServer/0/query takes the standard ArcGIS parameters: a where clause in standard SQL (AND/OR/NOT, comparisons, LIKE, IN, BETWEEN, IS NULL, dates), geometry with spatialRel and distance, objectIds, outFields, outSR, orderByFields, paging of up to 2,000 features, counts, ids, extents and statistics, answered as f=json, geojson or pbf. The five most valuable parcels in Norfolk, Virginia:

https://api.landrecords.us/arcgis/rest/services/parcel_us/FeatureServer/0/query?where=geoid%20%3D%20'51710'%20AND%20totalvalue%20%3E%2050000000&outFields=parceladdr,totalvalue&orderByFields=totalvalue%20DESC&resultRecordCount=5&returnGeometry=false&f=json&token=<TOKEN>

As with the WFS search, a query has to be narrowed by something an index serves:

  • objectIds, or a where on an indexed field: geoid, lrid, objectid, parcelid or parcelid2 (equality or a prefix LIKE), ownertype, accesstype, placetype, or an ownername match. These are always answered.
  • A geometry. Always answered. A where on other fields alone (totalvalue > 1000000) is answered inside a geometry of at most 100 km².
  • Counts, extents and statistics read up to 10,000 matches.

objectid is a 64-bit integer computed from lrid, so it is as permanent as lrid and does not change between data loads.

On parcel_us, the FeatureServer also publishes a Building permits table (1), related to the parcel layer through lrid, so a Map Viewer popup can list a parcel's permits.

Errors follow ArcGIS conventions: HTTP 200 with an error body whose code is 499 (no token), 498 (invalid token), 403 (not on your plan), 429 (over a limit) or 400 (a query that can't be answered). Tiles and export images answer with real HTTP statuses instead.

Parcel Detail Lookup

In addition to the tile services described above, the full WMS and WFS endpoints let you retrieve attribute details for an individual parcel. The two typical lookup patterns are by lon/lat (e.g. a click on a rendered map) and by lrid (a direct, attribute-based lookup). The parcel feature type is pro:parcel_us, served from:

  • WMS: https://api.landrecords.us/pro/wms
  • WFS: https://api.landrecords.us/pro/wfs

Both endpoints accept the same Bearer token used by the tile services. For brevity, the URL examples below use ?token=<TOKEN> so they can be pasted directly into a browser; programmatic clients should prefer the Authorization: Bearer <TOKEN> header instead.

Lookups are answered by PostGIS against the parcel polygons themselves — ST_Intersects on geom, not a proximity guess around a centroid — so "which parcel is at this point" has one exact answer.

Look up a parcel by lon/lat

The shortest form is our own vendor shortcut on the WFS endpoint:

https://api.landrecords.us/pro/wfs?lon=-76.2859&lat=36.8508&token=<TOKEN>

WMS GetFeatureInfo identifies features at a pixel inside a GetMap-style request. Send a small bounding box around your point and query the center pixel. Note the axis order: WMS 1.3.0 with EPSG:4326 expects bbox as minLat,minLon,maxLat,maxLon (this is the most common source of bad results — flip the order and you’ll silently query the wrong place).

https://api.landrecords.us/pro/wms
  ?service=WMS
  &version=1.3.0
  &request=GetFeatureInfo
  &layers=pro:parcel_us
  &query_layers=pro:parcel_us
  &crs=EPSG:4326
  &bbox=36.8507,-76.2860,36.8509,-76.2858
  &width=101&height=101
  &i=50&j=50
  &info_format=application/json
  &feature_count=1
  &token=<TOKEN>

GetFeatureInfo with info_format=application/json will return a GeoJSON FeatureCollection. A click sent alongside a cql_filter is AND-ed with it — "the parcel under the cursor, among those the filter allows" — rather than replacing it.

A point can lie in more than one parcel: on a shared boundary, or inside a stack of condo units drawn on one footprint. numberMatched says how many parcels contain it, and startIndex pages through them 10 at a time.

Look up a parcel by id

RESOURCEID (or its 1.1 spelling FEATUREID) fetches one feature directly:

https://api.landrecords.us/pro/wfs?request=GetFeature&resourceId=96708b9f-2f4b-398e-1c82-6fe77004432b&token=<TOKEN>

resourceId also takes a comma-separated list of up to 50 ids, and the response holds up to 10 of them, so ten parcels you already know cost one request instead of ten:

https://api.landrecords.us/pro/wfs?request=GetFeature&resourceId=<LRID_1>,<LRID_2>,<LRID_3>&token=<TOKEN>

cql_filter=lrid IN ('<LRID_1>','<LRID_2>') is the same lookup in filter form. Either way it is counted as a single parcel record request (see Usage and limits).

Search an area with a bounding box

A WFS GetFeature with a bbox returns every parcel whose polygon intersects the box — including parcels that only cross its edge, and parcels larger than the box itself:

https://api.landrecords.us/pro/wfs
  ?service=WFS
  &version=2.0.0
  &request=GetFeature
  &typeNames=pro:parcel_us
  &bbox=36.8500,-76.2900,36.8530,-76.2850,urn:ogc:def:crs:EPSG::4326
  &count=10
  &startIndex=0
  &outputFormat=application/json
  &token=<TOKEN>

The same request with curl and header-based auth:

curl -G 'https://api.landrecords.us/pro/wfs' \
  -H "Authorization: Bearer $LR_TOKEN" \
  --data-urlencode 'service=WFS' \
  --data-urlencode 'version=2.0.0' \
  --data-urlencode 'request=GetFeature' \
  --data-urlencode 'typeNames=pro:parcel_us' \
  --data-urlencode 'bbox=36.8500,-76.2900,36.8530,-76.2850,urn:ogc:def:crs:EPSG::4326' \
  --data-urlencode 'count=10' \
  --data-urlencode 'startIndex=0' \
  --data-urlencode 'outputFormat=application/json'

Coordinates are WGS84 degrees, and the axis order follows WFS 2.0: EPSG:4326 is minLat,minLon,maxLat,maxLon. Add a fifth value to make the order explicit — urn:ogc:def:crs:EPSG::4326 for latitude first, CRS:84 for longitude first (bbox=-76.2900,36.8500,-76.2850,36.8530,CRS:84 is the same box). Without one, the order is inferred from the numbers, which is reliable in North America (latitudes positive, longitudes negative) but not something to depend on. A box in projected units, such as EPSG:3857 metres, matches nothing — convert it to degrees first.

The response is a GeoJSON FeatureCollection. Each feature's id is its lrid, its geometry is the parcel polygon in EPSG:4326, and its properties hold the full attribute row (every property DescribeFeatureType lists), with a centroid alongside. numberMatched is the number of parcels in the whole box and numberReturned the number on this page.

Paging. A response holds at most 10 features. To read a whole box, repeat the request with startIndex advanced by 10 until you have numberMatched parcels:

  • Pages come back in lrid order, the same order on every request, so pages never repeat or skip a parcel. A sortBy (e.g. sortBy=totalvalue DESC) orders the whole box first, with lrid breaking ties; a descending sort puts parcels with no value first.
  • numberMatched and the stable order cover filters that match up to 10,000 parcels. Past that, numberMatched is null (WFS's "unknown") and, without a sortBy, the order is no longer guaranteed between requests — narrow the box or the filter to page through it.
  • Every page is a separate request against your query allowance: a box touching 45 parcels takes 5 requests. See Keeping area searches efficient.

Narrowing the box with attributes. Add a cql_filter to keep only some of the parcels in the box; the two are AND-ed:

bbox=36.8500,-76.2900,36.8530,-76.2850,urn:ogc:def:crs:EPSG::4326&cql_filter=totalvalue > 1000000

The box stands in for the indexed condition, so the filter may use any property. It can also be written inside the filter as a BBOX predicate, in the same axis order — cql_filter=BBOX(geom, 36.8500, -76.2900, 36.8530, -76.2850) AND totalvalue > 1000000 — where it counts toward the 3-predicate limit. bbox cannot be combined with FILTER or resourceId; with Filter Encoding, put a <fes:BBOX> inside the FILTER instead.

WFS GetFeature with cql_filter

The WFS endpoint accepts a cql_filter parameter to search parcels by attribute or spatial predicate, returning hydrated GeoJSON features (polygon geometry from ST_AsGeoJSON(geom), plus the full attribute row). Standard Filter Encoding 2.0 XML in a FILTER parameter is supported as well, over exactly the same property set; FILTER, RESOURCEID and BBOX are mutually exclusive, as the specification requires.

Filterable properties: every property DescribeFeatureType publishes — lrid, the 89 published parcel attributes (parcelid, ownername, totalvalue, zoningcode, parceladdr, yearbuilt, taxacres, fldzone, …) and geom. Naming anything else is reported as a client error rather than silently returning nothing.

Operators: =, <>, >, >=, <, <=, LIKE, ILIKE, IN, BETWEEN, IS [NOT] NULL, combined with AND, OR and parentheses. Text comparisons on the indexed columns are case-insensitive.

Spatial predicates, on the real parcel geometry:

  • BBOX — e.g. BBOX(geom, 37.7, -75.8, 37.9, -75.5). Returns every parcel whose polygon intersects the box, including parcels larger than the box itself.
  • DWITHIN — e.g. DWITHIN(geom, POINT(-75.6 37.7), 100, meters); distance is true metres on the spheroid.
  • INTERSECTS with a point — e.g. INTERSECTS(geom, POINT(-75.6 37.7)). An exact point-in-polygon test, the same one a map click uses.

One condition must be indexed

parcel_layer is 161M rows, and only these columns carry an index: lrid, parcelid, parcelid2, ownername, geoid, ownertype, accesstype, placetype. A filter that constrains none of them (and carries no spatial predicate) is a sequential scan that would end in the 20-second statement timeout, so it is refused up front with an ows:ExceptionReport naming the properties that work. One indexed condition is enough — geoid = '51710' AND usedesc ILIKE '%single family%' is fine, because geoid drives the scan and the rest filters it. Note that an OR is only as selective as its worst branch.

A bbox parameter, or the click of a GetFeatureInfo, sent alongside the filter counts as its indexed condition: the spatial index drives the scan, so bbox=…&cql_filter=totalvalue > 500000 needs nothing else.

statefp and countyfp together count as a geoid. The geoid column is the 5-character county FIPS — statefp followed by countyfp — so a filter that pins both (with = or IN, in the same AND group) is answered from the geoid index even though neither column is indexed on its own:

statefp = '48' AND countyfp = '113' AND totalvalue > 500000

works exactly like geoid = '48113' AND totalvalue > 500000. Either half alone is still refused.

At most 3 predicates besides the county

A filter may hold at most 3 predicates, not counting conditions on geoid, statefp or countyfp — the county anchor is free, everything else is bounded. Every predicate counts toward the one total, including spatial predicates and every branch of an OR; an IN (...) list or a BETWEEN is a single predicate however many values it names. So geoid = '48113' AND totalvalue > 500000 AND yearbuilt > 2000 AND bedrooms >= 3 is at the limit, and a fourth non-county condition is refused with an ows:ExceptionReport saying so.

A clause the parser cannot compile is likewise a 400, never silently dropped: a narrowed filter that reports success is indistinguishable from one that was honoured.

Special cases:

  • ownername is matched as full-text tokens rather than as a substring, so ownername = 'SMITH JOHN' finds the name in any order and ownername LIKE 'SMIT%' is a prefix search on the last token. A leading wildcard is unnecessary — token matching already means "contains".
  • LIKE on geoid is refused; use =, IN, or a BETWEEN over the 5-character county prefix.

Example request:

https://api.landrecords.us/pro/wfs?request=GetFeature&cql_filter=ownername%20LIKE%20'SMITH%25'&count=10&token=<TOKEN>

Control how many features are returned with count / maxFeatures / feature_count (default 10, hard maximum 10), and page with startIndex — see paging above. An unfiltered GetFeature returns an estimated numberMatched with zero features — a count, not a 161M-row download.

Other WMS operations

  • request=GetMap composites the raster pyramid into an arbitrary bbox and size (up to 4096 px per axis), for clients that want one image instead of a tile grid.
  • request=GetLegendGraphic returns the legend swatch.
  • request=DescribeFeatureType&typeNames=pro:parcel_us returns the GML 3.2 schema — the authoritative list of property names and types for both filter languages.

Usage and limits

Every successful (200) data request made with your token adds one to one of your plan's meters, however many parcels, features or bytes it returns. Errors, CORS preflights, and the public GetCapabilities, DescribeFeatureType and GetLegendGraphic documents are never counted, and neither are raster tiles. Your current counts are on Account → Subscriptions.

What each request counts as

Meter Shown in your account as Counted for
PARCEL_TILE_VECTOR Vector tile requests Each vector (pbf) tile.
PARCEL_TILE_RASTER Raster tile requests Nothing. Raster (png8) tiles, ArcGIS MapServer tiles included, are not metered on any plan that includes them, so they never count against a quota.
PARCEL_DETAILS Parcel record requests Single-parcel lookups: ?lon=&lat=, WMS GetFeatureInfo, INTERSECTS(geom, POINT(…)), resourceId / featureId, and lrid = … or lrid IN (…) filters.
PARCEL_QUERY Search queries (WFS / CQL) Every other request to /pro/wfs, /pro/wms or /pro/ows: bbox searches, cql_filter and FILTER searches (BBOX, DWITHIN, attribute conditions), unfiltered GetFeature counts, and WMS GetMap images.
mcp AI agent tool calls (MCP) Each tool call to the MCP server.

Canadian requests count on the same meters with a _CA suffix (PARCEL_QUERY_CA, …), shown in your account with "— Canada" after the name.

ArcGIS REST requests count on the same meters:

ArcGIS request Meter
VectorTileServer tile PARCEL_TILE_VECTOR
MapServer tile PARCEL_TILE_RASTER (not counted)
identify; a query by up to 10 objectIds, or at a point PARCEL_DETAILS
A draw query (resultType=tile) asking only for fields the vector tiles carry PARCEL_TILE_VECTOR
Any other query, count, ids, extent or statistics; find; export images PARCEL_QUERY
Service descriptions, styles, legends, the directory and sign-in Not counted

Parcel query limits

PARCEL_QUERY allowances by plan:

Plan US (PARCEL_QUERY) Canada (PARCEL_QUERY_CA)
Free Trial 1,000 1,000
Pro Plan 10,000 per month Not included
Pro Canada Not included 10,000 per month
Pro North America 10,000 per month 10,000 per month

On a plan that doesn't include the meter, a search answers 403 with Your plan does not include this feature.; a Canadian search on a US-only plan answers with a message pointing at Pro Canada and Pro North America instead.

Going over a limit

Every meter's counter resets at 00:05 UTC on the 1st of each month. When a key passes a meter's allowance we add 50% more to that meter's quota for the month at no charge, and email the address on the account to say so. The meter keeps serving up to 200% of the allowance; the extra 50% counts toward that, it does not raise it. Past 200%, the meter's requests answer 429 Too Many Requests until the reset — the key's other meters keep working:

{
  "error": "This key has made 20000 PARCEL_QUERY requests this month, past its limit of 15000 (10000 on its plan + 5000 added at no charge) and the 20000 that PARCEL_QUERY requests stop at. ...",
  "meter": "PARCEL_QUERY",
  "limit": 15000,
  "ceiling": 20000,
  "used": 20000,
  "resets": "2026-11-01T00:05:00.000Z"
}

The response's Retry-After header gives the seconds until the reset. Refused requests are not counted. We email the address on the account when a meter reaches 80% of its allowance and again when it passes 100% and the extra quota is added; if you regularly need more, contact us about a larger or custom plan.

Keeping area searches efficient

A request counts once whatever it returns, but returns at most 10 parcels. So:

  • A bounding box costs one request per 10 parcels it touches — ⌈N ÷ 10⌉ requests for N parcels. The first page's numberMatched tells you N before you spend the rest.
  • A box returns every parcel it touches, not only the ones you want. It saves requests only when the parcels you're after make up most of the box: four parcels in a block of 60 cost 6 box requests, 4 single lookups, or 1 lookup by a list of ids.
  • Look up parcels you already know by id. resourceId=<id>,<id>,… returns up to 10 known parcels per request, with no neighbours taking up the slots, and counts as one parcel record request. Use a box to discover parcels and ids to refresh them.
  • Narrow the box with attributes (BBOX(…) AND …) so every page holds only parcels you'll use.
  • Prefer several small boxes to one large one. Each page re-runs the search over the whole box and sorts it, so pages of a very large box are slow, and a search that runs past 20 seconds is cancelled with a 504.
  • For drawing or hit-testing many parcels, use vector tiles. One tile delivers every parcel in it with the tile attributes — hundreds of parcels in a built-up z16 tile — and counts once, on the vector tile meter.

Querying from an AI assistant or agent

The same serving layer is also exposed over the Model Context Protocol at https://api.landrecords.us/mcp, so Claude — or any MCP-aware client or agent — can query parcels directly through eight structured, read-only tools instead of hand-written CQL. Authentication is the same token used above, sent as Authorization: Bearer <YOUR_TOKEN>, and MCP access is included in the Pro plan.

See the Parcel MCP Server documentation for endpoints, the tool reference, and agent examples.

Secure Parcel Layer Web Services

Visit https://landrecords.us/enterprise-web-service to learn more.

On this page