Skip to content

Check 3DEP lidar coverage

You are viewing in-progress documentation for v2. Switch to the stable version for the current production release.

GET /domains/{domain_id}/pointclouds/3dep/coverage answers four questions about a domain before you spend anything on it: is there public lidar here, whose is it, how dense is it, and how many points will a fetch return?

It is a catalog lookup and some geometry — no point data is read — so it returns immediately. Every failure mode of fetching a 3DEP point cloud is visible here first, which is the reason to run it.

  1. An API key: my-api-key.

  2. A domain: your-domain-id. See Create a domain.

GET pointclouds/3dep/coverage
curl -X 'GET' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/pointclouds/3dep/coverage' \
-H 'accept: application/json' \
-H 'api-key: my-api-key'
FieldWhat to do with it
availablefalse means a create request will be rejected. Stop here.
coverage_fractionThe share of the domain any 3DEP lidar covers, 0.0–1.0. See the caveat below.
estimated_point_countRoughly how many points a fetch would return.
datasets[]The acquisitions that would be read, in the order they would be used.

Each entry in datasets[] describes one USGS acquisition:

  • name — pass it back in datasets on the create request to pin the fetch to this acquisition.
  • contribution_fraction — the share of the domain this acquisition would supply. Acquisitions overlap freely, so this is what is left over after the ones listed before it have taken their part, not the raw overlap. The values are disjoint and sum to coverage_fraction.
  • estimated_density — average points per square metre over the acquisition’s full published extent.
  • estimated_points — derived from density and area, so treat it as an order of magnitude rather than a count.

Some parts of the country do not have 3DEP lidar data available. When that is the case the response is unambiguous and datasets is empty:

{
"available": false,
"coverage_fraction": 0.0,
"datasets": [],
"estimated_point_count": 0
}

A create request against this domain returns a 422 (“No USGS 3DEP lidar is available for this domain”). Your options are a different area, or a canopy source that does not need lidar — NAIP and Meta both produce a chm band without one, and neither has coverage gaps. See Choosing a source.

When no single survey covers the domain, the backend combines the fewest that fill it. Here two acquisitions are needed, and they are not equivalent — the first supplies 87.7% of the domain at 28.3 pts/m², the second the remaining 12.3% at 3.0 pts/m², nearly ten times sparser:

{
"available": true,
"coverage_fraction": 1.0,
"datasets": [
{
"name": "AZ_MohaveCoconino_1_D23",
"url": "https://s3-us-west-2.amazonaws.com/usgs-lidar-public/AZ_MohaveCoconino_1_D23/ept.json",
"contribution_fraction": 0.8773581560283717,
"estimated_density": 28.31556851085709,
"estimated_points": 9534173
},
{
"name": "AZ_MohaveCo_2_2021",
"url": "https://s3-us-west-2.amazonaws.com/usgs-lidar-public/AZ_MohaveCo_2_2021/ept.json",
"contribution_fraction": 0.12264184397162811,
"estimated_density": 2.9543377555480443,
"estimated_points": 139052
}
],
"estimated_point_count": 9673225
}
Two horizontal bar charts sharing one list of acquisitions. The left shows AZ_MohaveCoconino_1_D23 supplying 87.7 percent of the domain and AZ_MohaveCo_2_2021 supplying 12.3 percent. The right shows their estimated densities as 28.3 and 3.0 points per square metre respectively. Each acquisition keeps its colour in both charts. Two horizontal bar charts sharing one list of acquisitions. The left shows AZ_MohaveCoconino_1_D23 supplying 87.7 percent of the domain and AZ_MohaveCo_2_2021 supplying 12.3 percent. The right shows their estimated densities as 28.3 and 3.0 points per square metre respectively. Each acquisition keeps its colour in both charts.

The same two acquisitions, by share of the domain and by density. The minority acquisition is nearly ten times sparser — read both panels, not just the first.

This is worth looking at rather than skipping past. A mosaic puts a seam between flights of different dates and densities through your data, and downstream products inherit it — a CHM built across this domain is detailed on one side of the seam and coarse on the other. If that matters, pin the better acquisition and accept partial coverage rather than taking both.

There is no limit on the number of points in a fetch; the 16 km² domain cap is what bounds one. This domain is a 3.92 km square (about 15.4 km², just under the cap) over one dense acquisition, and the estimate is 227.6 million points:

{
"available": true,
"coverage_fraction": 1.0,
"datasets": [
{
"name": "MT_Statewide_P3_4_B21",
"url": "https://s3-us-west-2.amazonaws.com/usgs-lidar-public/MT_Statewide_P3_4_B21/ept.json",
"contribution_fraction": 1.0,
"estimated_density": 14.811981421134373,
"estimated_points": 227552496
}
],
"estimated_point_count": 227552496
}

A create request over this domain is accepted. Read a large estimate as a long job and a large cloud to store and download, and set your own ceiling if you want one, as the Python example above does. Density and area together decide the estimate, so a small domain over dense lidar can reach a large one as easily as a large domain over sparse lidar.

  • Skipping the pre-flight and reading source.coverage_fraction afterwards. Both report the same number, but only one of them is free. A rejected create request costs a round trip; a fetch that succeeds with a hole in it costs a background job and everything you build on it.
  • Treating estimated_point_count as a count. It is derived from published density over published extent. In a verified run the estimate was 7,847,291 and the fetch returned 10,512,255 — within an order of magnitude, not within a rounding error.
  • Assuming a covered domain is a uniformly covered domain. Read datasets[].estimated_density before you assume the far corner is as good as the near one.
  • Pinning an acquisition without checking coverage first. Names come from this endpoint. An acquisition that does not exist, or that exists but does not overlap your domain, is a 422 with two different messages.