Load GeoJSON-NL into BigQuery
Use the bq CLI (or LOAD DATA SQL) to ingest a Land Records .geojsonl file directly into a BigQuery table with a native GEOGRAPHY column.
BigQuery natively ingests newline-delimited GeoJSON. Each line in a .geojsonl file is a complete GeoJSON Feature, and BigQuery promotes the geometry field to a GEOGRAPHY column automatically.
Prerequisites
- The
bqCLI installed and authenticated (gcloud auth login). - A BigQuery dataset to load into. If you don't have one yet:
bq mk --location=US --dataset my_project:landrecords- The Land Records GeoJSON-NL download on local disk, or in a GCS bucket you can read.
1. Load from local disk
bq load \
--source_format=NEWLINE_DELIMITED_JSON \
--json_extension=GEOJSON \
--autodetect \
my_project:landrecords.parcels \
./parcels-2026.2.geojsonl--json_extension=GEOJSON is the option that tells BigQuery to convert each Feature's geometry field into a GEOGRAPHY column. Without it, the geometry would land as a nested STRUCT.
--autodetect infers column names and types from the first few hundred rows. For a stable production pipeline you should provide an explicit schema instead — see the schema-first variant below.
2. Load from GCS (recommended for files >1 GB)
gsutil cp ./parcels-2026.2.geojsonl gs://my-bucket/landrecords/
bq load \
--source_format=NEWLINE_DELIMITED_JSON \
--json_extension=GEOJSON \
--autodetect \
my_project:landrecords.parcels \
gs://my-bucket/landrecords/parcels-2026.2.geojsonlLoading from GCS is parallelized across BigQuery slots and is dramatically faster than uploading from a workstation. For the nationwide download (~50–80 GB GeoJSON-NL), this is the only practical path.
3. Schema-first load (no autodetect)
For production pipelines, pin the schema so BigQuery doesn't have to scan and so type promotions are predictable. The complete schema for public.lr_parcel_us is below — download it as parcels-bigquery-schema.json (or copy it from here), then pass it with --schema:
[
{ "name": "lrid", "type": "STRING", "mode": "REQUIRED" },
{ "name": "parcelid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parcelid2", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ogparcelid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ogparcelid2", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parentid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "stackid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "geoid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "statefp", "type": "STRING", "mode": "NULLABLE" },
{ "name": "countyfp", "type": "STRING", "mode": "NULLABLE" },
{ "name": "countyname", "type": "STRING", "mode": "NULLABLE" },
{ "name": "cousubfp", "type": "STRING", "mode": "NULLABLE" },
{ "name": "cousubname", "type": "STRING", "mode": "NULLABLE" },
{ "name": "tractce", "type": "STRING", "mode": "NULLABLE" },
{ "name": "tractname", "type": "STRING", "mode": "NULLABLE" },
{ "name": "taxacctnum", "type": "STRING", "mode": "NULLABLE" },
{ "name": "taxyear", "type": "INT64", "mode": "NULLABLE" },
{ "name": "taxdistrict", "type": "STRING", "mode": "NULLABLE" },
{ "name": "usecode", "type": "STRING", "mode": "NULLABLE" },
{ "name": "usedesc", "type": "STRING", "mode": "NULLABLE" },
{ "name": "zoningcode", "type": "STRING", "mode": "NULLABLE" },
{ "name": "zoningdesc", "type": "STRING", "mode": "NULLABLE" },
{ "name": "numbldgs", "type": "INT64", "mode": "NULLABLE" },
{ "name": "numunits", "type": "INT64", "mode": "NULLABLE" },
{ "name": "yearbuilt", "type": "INT64", "mode": "NULLABLE" },
{ "name": "numfloors", "type": "INT64", "mode": "NULLABLE" },
{ "name": "bldgsqft", "type": "INT64", "mode": "NULLABLE" },
{ "name": "bedrooms", "type": "INT64", "mode": "NULLABLE" },
{ "name": "halfbaths", "type": "INT64", "mode": "NULLABLE" },
{ "name": "fullbaths", "type": "INT64", "mode": "NULLABLE" },
{ "name": "imprvalue", "type": "INT64", "mode": "NULLABLE" },
{ "name": "landvalue", "type": "INT64", "mode": "NULLABLE" },
{ "name": "agvalue", "type": "INT64", "mode": "NULLABLE" },
{ "name": "totalvalue", "type": "INT64", "mode": "NULLABLE" },
{ "name": "taxacres", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "calcarea", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "saleamt", "type": "INT64", "mode": "NULLABLE" },
{ "name": "saledate", "type": "DATE", "mode": "NULLABLE" },
{ "name": "ownertype", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ownername", "type": "STRING", "mode": "NULLABLE" },
{ "name": "owneraddr", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ownercity", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ownerstate", "type": "STRING", "mode": "NULLABLE" },
{ "name": "ownerzip", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parceladdr", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parcelcity", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parcelstate", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parcelzip", "type": "STRING", "mode": "NULLABLE" },
{ "name": "legaldesc", "type": "STRING", "mode": "NULLABLE" },
{ "name": "township", "type": "STRING", "mode": "NULLABLE" },
{ "name": "section", "type": "STRING", "mode": "NULLABLE" },
{ "name": "qtrsection", "type": "STRING", "mode": "NULLABLE" },
{ "name": "range", "type": "STRING", "mode": "NULLABLE" },
{ "name": "plssdesc", "type": "STRING", "mode": "NULLABLE" },
{ "name": "book", "type": "STRING", "mode": "NULLABLE" },
{ "name": "page", "type": "STRING", "mode": "NULLABLE" },
{ "name": "block", "type": "STRING", "mode": "NULLABLE" },
{ "name": "lot", "type": "STRING", "mode": "NULLABLE" },
{ "name": "parceltype", "type": "STRING", "mode": "NULLABLE" },
{ "name": "accesstype", "type": "STRING", "mode": "NULLABLE" },
{ "name": "iucnclass", "type": "STRING", "mode": "NULLABLE" },
{ "name": "placename", "type": "STRING", "mode": "NULLABLE" },
{ "name": "placetype", "type": "STRING", "mode": "NULLABLE" },
{ "name": "firmid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "firmdate", "type": "DATE", "mode": "NULLABLE" },
{ "name": "fldzone", "type": "STRING", "mode": "NULLABLE" },
{ "name": "zonesubty", "type": "STRING", "mode": "NULLABLE" },
{ "name": "staticbfe", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "elevmin", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "elevmax", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "elevavg", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "fireplaces", "type": "INT64", "mode": "NULLABLE" },
{ "name": "heating", "type": "STRING", "mode": "NULLABLE" },
{ "name": "heatfuel", "type": "STRING", "mode": "NULLABLE" },
{ "name": "cooling", "type": "STRING", "mode": "NULLABLE" },
{ "name": "foundation", "type": "STRING", "mode": "NULLABLE" },
{ "name": "roofcover", "type": "STRING", "mode": "NULLABLE" },
{ "name": "siding", "type": "STRING", "mode": "NULLABLE" },
{ "name": "bldgtype", "type": "STRING", "mode": "NULLABLE" },
{ "name": "naicscode", "type": "STRING", "mode": "NULLABLE" },
{ "name": "frsid", "type": "STRING", "mode": "NULLABLE" },
{ "name": "dfrurl", "type": "STRING", "mode": "NULLABLE" },
{ "name": "caapermit", "type": "STRING", "mode": "NULLABLE" },
{ "name": "cwapermit", "type": "STRING", "mode": "NULLABLE" },
{ "name": "rcrapermit", "type": "STRING", "mode": "NULLABLE" },
{ "name": "updated", "type": "DATE", "mode": "NULLABLE" },
{ "name": "centroidx", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "centroidy", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "surfpointx", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "surfpointy", "type": "FLOAT64", "mode": "NULLABLE" },
{ "name": "extras", "type": "JSON", "mode": "NULLABLE" },
{ "name": "lrversion", "type": "STRING", "mode": "NULLABLE" },
{ "name": "geometry", "type": "GEOGRAPHY", "mode": "REQUIRED" }
]Then load:
bq load \
--source_format=NEWLINE_DELIMITED_JSON \
--json_extension=GEOJSON \
--schema=./parcels-bigquery-schema.json \
--clustering_fields=statefp,countyfp,geometry \
my_project:landrecords.parcels \
gs://my-bucket/landrecords/parcels-2026.2.geojsonlAdd --clustering_fields=statefp,countyfp,geometry so common state/county filters — and spatial predicates like ST_DWITHIN / ST_INTERSECTS — scan only a fraction of the table. BigQuery clusters a GEOGRAPHY column by the S2 covering of each geometry, so the trailing geometry field accelerates the location queries in §5. (The loaded column is named geometry, not geom — that's the field BigQuery creates from each GeoJSON Feature's geometry.)
This is the complete 2026.2 schema generated directly from public.lr_parcel_us: 92 attribute columns plus the geometry GEOGRAPHY field. Every attribute is NULLABLE except lrid (the UUID primary key) and geometry, which are REQUIRED; see Table Schema for per-column descriptions. To load only a subset, delete the lines you don't need and add --ignore_unknown_values so BigQuery skips the GeoJSON properties that have no matching column.
4. Verify
SELECT
statefp,
parcelstate,
COUNT(*) AS parcels,
ROUND(SUM(calcarea) / 1e6, 1) AS total_km2
FROM `my_project.landrecords.parcels`
GROUP BY 1, 2
ORDER BY parcels DESC
LIMIT 10;5. Common geospatial queries
Parcels within 5 miles of a point:
SELECT lrid, ownername, parceladdr
FROM `my_project.landrecords.parcels`
WHERE ST_DWITHIN(
geometry,
ST_GEOGPOINT(-86.81, 33.52),
5 * 1609.344
);Parcels that intersect a custom polygon:
SELECT lrid, calcarea
FROM `my_project.landrecords.parcels`
WHERE ST_INTERSECTS(
geometry,
ST_GEOGFROMTEXT('POLYGON((-87 33, -86.8 33, -86.8 33.2, -87 33.2, -87 33))')
);Troubleshooting
Invalid GeoJSON feature— almost always a row with anullgeometry. The Land Records dataset does not emit null geometries, but if you produced the.geojsonlyourself with a custom SQL query, filterWHERE geom IS NOT NULLbefore exporting.Field geometry has type ... expected GEOGRAPHY— you forgot--json_extension=GEOJSON.Quota exceeded: Maximum size of HTTP request payload— load from GCS, not from a local file.