How to Collect Google Street View Data at Scale with Official APIs
The official route starts with free metadata, then permitted image requests. At city scale, sampling, quota, cost, retries, QA and a traceable manifest become the real collection job.
- Author
- HuiTu Technology
- Published
- Updated
If you need Google Street View as data — not as a map you pan by hand — the supported way is the Street View Static API. It is an HTTP image service: you send a location and camera parameters, Google returns a JPEG. There is no documented bulk-export of raw 360° files, and there is no licence to scrape the consumer Street View website.
This article explains the official collection method from pilot to city scale: how the endpoints differ, which parameters define the image, how to design a repeatable sampling frame, how billing and terms constrain storage, and when request orchestration, quality control and provenance become a production data pipeline rather than a short script.
Two endpoints, two jobs
| Endpoint | Returns | Billed as an image? |
|---|---|---|
| streetview/metadata | JSON: status, snapped location, capture month, pano_id, copyright | No. Google documents metadata as free of charge and as not consuming image quota. |
| streetview | A perspective JPEG at the size you requested, up to 640 × 640 pixels | Yes. Each successful image request is a billed Static Street View panorama. |
Always run metadata first. If status is not OK, there is nothing to fetch, and you should not pay for a grey placeholder. When you do request an image, set return_error_code=true so a miss comes back as an HTTP error instead of a generic grey frame that a pipeline will happily save.
The parameters that define one picture
An image request is a URL. Required pieces are an API key, a size, and either a location (address or latitude,longitude) or a panorama id. Optional camera controls decide what the JPEG actually shows.
- location or pano: the search origin. With coordinates, the API looks within a radius (default 50 m) for the nearest panorama. Panorama ids change over time; store coordinates, not ids, if you need to refresh later.
- size: width × height in pixels, maximum 640 × 640 on this API.
- heading: compass direction, 0–360. Four headings (0°, 90°, 180°, 270°) are the usual research pattern so one camera angle does not decide how green or how enclosed a street looks.
- fov: horizontal field of view, default 90, maximum 120. Smaller values look more zoomed in.
- pitch: tilt relative to the vehicle, default 0. Keep it near horizontal unless you have a reason; a slight upward tilt inflates sky share.
- source=outdoor: skip indoor panoramas that sit near a street sample.
- signature: a digital signature on the URL. Google recommends it; some billing plans require it.
import os
from urllib.parse import urlencode
import requests
KEY = os.environ["GOOGLE_MAPS_API_KEY"] # never hard-code a key
META = "https://maps.googleapis.com/maps/api/streetview/metadata"
IMAGE = "https://maps.googleapis.com/maps/api/streetview"
def fetch_heading(lat, lon, heading, path):
"""Check coverage first, then request one billed perspective JPEG."""
meta = requests.get(
META,
params={"location": f"{lat},{lon}", "source": "outdoor", "key": KEY},
timeout=10,
).json()
if meta.get("status") != "OK":
return meta.get("status")
params = {
"location": f"{lat},{lon}",
"size": "640x640",
"heading": heading,
"fov": 90,
"pitch": 0,
"source": "outdoor",
"return_error_code": "true",
"key": KEY,
}
response = requests.get(IMAGE, params=params, timeout=20)
response.raise_for_status()
with open(path, "wb") as handle:
handle.write(response.content)
return "OK"
# Example: one sample point, four compass headings
# fetch_heading(40.7536, -73.9804, 0, "heading-000.jpg")
print(urlencode({"size": "640x640", "heading": 90})) # inspect query shape only

Billing and throughput
Image requests are pay-as-you-go under the Static Street View SKU. Metadata is a separate SKU that Google lists as free. There is a documented usage cap of 30,000 queries per minute; for a research script the binding constraint is usually cost and the terms, not that cap. Enable billing, keep the key in an environment variable, and put a daily quota in Google Cloud so a loop cannot run away.
What this method is good for
- A handful of sites: a thesis figure, a methods appendix, or a client sample of twenty points.
- A coverage-and-age check across a district, using metadata only, before anyone spends on images.
- A four-heading pack per point so a segmentation model sees a comparable street, not a single lucky angle.
At that scale you can run the official API yourself: one key, a CSV of coordinates, metadata, then images. The work is mostly sampling design and not mixing capture months.
When you need it at city scale
A metro road network sampled every 25 metres, four headings each, is tens or hundreds of thousands of image requests, plus retries, grey-image checks, coordinate snapping, vintage control and a manifest that ties every number back to a source image. That is no longer a weekend script. It is a collection job: quota and billing, sampling geometry, licence-aware storage, and validation before analysis starts.
Related services
- Large-Scale Street View Data CollectionOfficial-API and permitted-source acquisition with coverage audit, QA, traceable metadata and optional processing.
- Request a QuoteSend the area and the fields. You get a written scope and a fixed price first.
- Semantic SegmentationTurn sampled street-level frames into class shares and indicators.