A note on the imagery in this post. To avoid any copyright issues, this notebook contains no real Google Street View imagery. Google's Map Tiles API terms do not permit redistributing, caching, or printing the served panoramas, so every panorama shown here — including the “real-world” locations in Section 5 — has been replaced with synthetic data: fictional 360° scenes generated with OpenAI's gpt-image-2 model, together with a public-domain NASA panorama. These are AI illustrations, not photographs and not real Street View. The genuine Street View API calls are kept as runnable code so you can fetch the real imagery yourself, with your own API key, under Google's own attribution and terms.
Inspired by Diego Zviovich's recent Wolfram Community posts "Google Earth Engine (GEE) client paclet" and "Google Earth Engine (GEE) paclet: satellite imagery fundamentals", which prompted me to look at what could be done with the neighbouring Google Maps Platform Street View Tiles API from Wolfram Language.
Setup -- evaluate this first
Setup -- evaluate this first
Before reading further, evaluate the cell below once. It loads the StreetView360 package and a small embedded sample panorama from the two .wl files that ship with this notebook (StreetView360.wl and demo_panorama.wl). Every other code-styled block in the notebook is either runnable Wolfram Language that depends on this step or a documentation listing that the notebook will not evaluate. The cell prints exactly what it looked for and what it loaded so you can see the outcome at a glance.
(*Locatethetwo.wlfiles.Samedirectoryasthenotebookisthenatural"download both files into one folder"conventionusedontheWolframCommunity;thefallbackistheKernel/siblinginsideafullrepositoryclone.*)$nbDir=Quiet@NotebookDirectory[];$pkgGuesses=DeleteCases[{If[StringQ[$nbDir],FileNameJoin[{$nbDir,"StreetView360.wl"}],Null],FileNameJoin[{Directory[],"StreetView360.wl"}],If[StringQ[$nbDir],FileNameJoin[{ParentDirectory[$nbDir],"Kernel","StreetView360.wl"}],Null]},Null];Print["NotebookDirectory[]: ",$nbDir];Print["Looking for StreetView360.wl in:"];Print[" - ",#," (exists: ",FileExistsQ[#],")"]&/@$pkgGuesses;$pkgPath=SelectFirst[$pkgGuesses,FileExistsQ,$Failed];If[StringQ[$pkgPath],Get[$pkgPath];Print["Loaded package: ",$pkgPath];Print["Public symbols in StreetView360`: ",Names["StreetView360`*"]];$demoPath=FileNameJoin[{DirectoryName[$pkgPath],"demo_panorama.wl"}];If[FileExistsQ[$demoPath],Get[$demoPath];Print["Loaded demo panorama: ",$demoPath]],Print[""];Print["** StreetView360.wl was NOT found in any of the locations above. **"];Print["Either place StreetView360.wl in the same folder as this notebook,"];Print["or set $pkgPath to its absolute path and Get[$pkgPath] manually."]]
Abstract
Abstract
Google Street View ships every 360° panorama as a collection of square JPEG tiles served by the Map Tiles API (Essentials tier, 100000 free calls per month). This notebook walks through a small Wolfram-Language paclet, StreetView360, which authenticates against the API, fetches the tiles for a chosen location, composites them into a single equirectangular image, texture-maps that image onto a sphere, and views the sphere from the inside with Manipulate controls for yaw, pitch, and field of view. Every piece is plain Wolfram Language — no MathLink, no external paclet dependencies. The API key is stored in the operating-system keychain via SystemCredential and is never written to disk by the package.
1. What is a Street View panorama?
1. What is a Street View panorama?
A Street View image is not a flat photograph but a full 360° panorama: at every (heading, pitch) direction from the capture point there is a pixel. Google's API serves this panorama in the equirectangular (a.k.a. plate carrée) projection — a single rectangular image whose columns are linear in heading and whose rows are linear in pitch. This is the simplest of all sphere-to-plane projections: it puts the 2:1 aspect ratio onto the sphere with no clever surgery.
For an image of width and height , normalised pixel coordinates with , (origin at the top-left) map to spherical angles by
W
H
(u,v)
u=x/W
v=y/H
(θ,ϕ)=(2πu,π(1-v)),u,v∈[0,1]
so heading and elevation are simply linear functions of the pixel position. The aspect ratio falls out of mapping onto the horizontal axis and onto the vertical.
W:H=2:1
[0,2π]
[0,π]
2. The Street View Tiles API
2. The Street View Tiles API
The API is RESTful and centres on three endpoints. All three require an API key with the Map Tiles API enabled. The package reads the key from SystemCredential["GoogleMapsAPIKey"] (macOS Keychain / Windows Credential Manager / libsecret on Linux) so it never lives in any source file.
2.1 Sessions
2.1 Sessions
A session token authenticates a batch of tile/metadata requests and lasts up to two weeks. The package caches it in private symbols and refreshes 60 s before expiry.
POSThttps://tile.googleapis.com/v1/createSession?key=API_KEYContent-Type:application/json{"mapType":"streetview","language":"en-US","region":"US"}{"session":"abcd...",(*opaquetoken*)"expiry":"1714400000",(*Unixepochseconds*)"tileWidth":512,"tileHeight":512,"imageFormat":"image/jpeg"}
2.2 Metadata
2.2 Metadata
Given a coordinate (or a known panoId), the metadata endpoint returns the panorama's identifier, its native dimensions, the capture date, and the copyright attribution. The package wraps this in getPanoMetadata:
The lookup tolerates several location formats: {lat, lng}, GeoPosition[{lat, lng}], or a panoId string. Failures are distinguished: a 404 produces StreetView360::nopano; any other status produces StreetView360::apierr.
2.3 Tiles
2.3 Tiles
Each tile is fetched independently:
and the response body is the raw image bytes. The package's fetchTile function decodes them with ImportByteArray, honouring the imageFormat reported by the session (JPEG by default, with a PNG fallback). 404 tiles become Missing["NotAvailable"], everything else stays an Image.
3. From tiles to a sphere
3. From tiles to a sphere
3.1 Compositing the tiles
3.1 Compositing the tiles
3.2 Texture-mapping onto a sphere
3.2 Texture-mapping onto a sphere
The unit sphere has the standard parameterisation
In Wolfram, the entire textured sphere is one call to ParametricPlot3D:
3.3 Viewing from inside the sphere
3.3 Viewing from inside the sphere
If you render that sphere with a default camera, you see the outside of a textured ball — which is not what a Street View viewer should look like. We place the camera at the origin, inside the sphere, and let the user rotate its look-direction:
4. The StreetView360 package
4. The StreetView360 package
4.1 Setup
4.1 Setup
Get an API key from the Google Cloud Console, enable the Map Tiles API, and store it in the OS keychain once. The right way to do this is to type the assignment below yourself in a fresh notebook (substituting your actual key for "AIza...") and evaluate it once. The listing below is for reference only — this notebook deliberately makes it non-evaluatable so that pressing Shift+Enter cannot overwrite your real key with the literal placeholder string.
Loading the package itself is handled by the Setup cell at the top of this notebook — no other load step is needed.
4.2 Top-level usage
4.2 Top-level usage
streetView360 is the one-call convenience that runs the whole pipeline:
Returned object is a DynamicModule wrapping a Manipulate, evaluatable inside the notebook. The three sliders are heading, pitch, and fov (deg).
4.3 Low-level primitives
4.3 Low-level primitives
All four building blocks are exposed and can be used independently:
5. Examples
5. Examples
Each example below presents a panorama three ways: the call that produces it, the full equirectangular returned by fetchPanorama, and a hyperlink to a browser-side 360° viewer hosted on the Wolfram Cloud that lets readers without Mathematica click, drag, and zoom through the same panorama.
If you are reading the notebook live and want a drag-to-look viewer in the notebook itself, the panoViewer in the package uses sliders. The cell below defines an alternative viewer panoDragViewer that responds to click-and-drag (yaw / pitch) and the scroll wheel (FOV). Evaluate it once, then call panoDragViewer[img] on any equirectangular Image. The whole definition is short enough to drop straight into the notebook — no separate file is needed.
Try it immediately, with no API key required. The Setup cell at the top of this notebook already loaded a small embedded sample panorama into the symbol demoPanorama. This sample is a fictional equirectangular panorama generated with OpenAI's gpt-image-2 — it is an AI illustration, deliberately not a real Google Street View panorama. Google's Map Tiles API terms do not permit redistributing, caching, or printing the served imagery, so no real panorama is embedded anywhere in this post; the genuine fetch calls are shown as runnable code that you can evaluate with your own key. The AI sample exists purely so the viewer below has something to texture-map without any network access. Evaluating the one-line cell feeds it to panoDragViewer. Drag the rendered view to look around, click zoom +/zoom − to change the field of view (scroll-wheel zoom works in the desktop front end but not in the Wolfram Cloud / Community browser viewer, where the buttons are the portable equivalent), and Reset to recentre.
Heads up: the interactive cell above is fully draggable in desktop Mathematica or the Wolfram Player. The browser-side notebook viewer that powers Wolfram Community does not render its mouse interaction — you will see a static preview instead. Click here for a self-contained 360° browser viewer of this panorama (a Three.js page hosted on the Wolfram Cloud, opens in a new tab) that responds to click-and-drag and pinch-zoom natively.
Use the same call on any 2:1 equirectangular image — one fetched from the API (if you have a key), one imported from disk, anything you can get into an Image object. The line below fetches a real St Andrews panorama straight from Google and views it; it requires SystemCredential["GoogleMapsAPIKey"] to be set. The output is not reproduced here — running the call yourself displays it under Google's own attribution and report-a-problem terms.
For sharing a panorama with someone who does not have Mathematica, the deployed HTML viewers at this index page let any reader explore the panoramas in the browser. Only imagery we are free to redistribute is hosted there — the synthetic gpt-image-2 panoramas and the public-domain NASA capture; the Google Street View examples are not, since the Map Tiles API terms do not permit it. The viewers are self-contained Three.js pages with the image inlined as a base64 data URL; the source template is at community/viewer_template.html and the generator at community/generate_html_viewers.wls.
A note on coverage. The Map Tiles API serves two kinds of panoramas through the same endpoints: Google's official car/trike-captured imagery, which is a full 360° × 180° sphere minus a small nadir patch (where the capture vehicle would be), and user-contributed Photo Spheres, which are often hemispherical — capturing only the upper half of the sphere. The package returns whatever the API serves, so the lower hemisphere of a hemispherical panorama is filled with black; this also shows up as a black "floor" in the inside-the-sphere viewer. The two kinds are described below — with synthetic stand-ins in place of the real Google imagery, which the Map Tiles API terms do not let us reproduce here.
5.1 Trafalgar Square, London (gpt-image-2 illustration)
5.1 Trafalgar Square, London (gpt-image-2 illustration)
5.2 Times Square at night (gpt-image-2 illustration)
5.2 Times Square at night (gpt-image-2 illustration)
5.3 St Andrews — full-sphere scene (gpt-image-2 illustration)
5.3 St Andrews — full-sphere scene (gpt-image-2 illustration)
5.4 Looking up panoIds with the metadata endpoint
5.4 Looking up panoIds with the metadata endpoint
Once you have used getPanoMetadata to find a panorama near a coordinate, the returned panoId is a stable handle: the same panorama can be re-fetched indefinitely (until Google retires the imagery) without paying for another metadata lookup. This is particularly useful when scripting a tour through multiple known locations:
6. Places Google Maps cannot take you
6. Places Google Maps cannot take you
The Map Tiles API gets us to every paved road and a startling number of contributor-uploaded Photo Spheres, but it stops there. The panoramas in this section are the ones it cannot give us — the surface of Mars, the surface of the Moon, an underwater coral reef. Three of them were generated with OpenAI's gpt-image-2 image model, asked explicitly for the equirectangular plate carrée projection (columns linear in heading, rows linear in pitch, left and right edges connecting at heading 180°) so that when panoDragViewer texture-maps them onto a sphere they read as proper 360° scenes rather than as a flat photo wrapped onto a ball. This is the difference between the gpt-image-1 family, which silently rejects the projection request and returns a perspective image, and gpt-image-2, which actually understands the convention. A real NASA Perseverance rover panorama is included alongside the synthetic Mars view so you can compare a genuine in-situ capture to the generated one.
All three synthetic panoramas were generated at 2048×1024 and inlined in demo_panorama.wl as marsPanorama, moonPanorama, and reefPanorama. The real NASA panorama is inlined as marsRealPanorama. Once the Setup cell has run all four are in scope and can be fed to panoDragViewer.
6.1 Standing on Mars (synthetic, gpt-image-2)
6.1 Standing on Mars (synthetic, gpt-image-2)
Rust-orange regolith, scattered basalt rocks, a hazy salmon-pink sky meeting the horizon, a distant shield volcano in one heading direction, and a star-flecked Martian night sky overhead. Generated by gpt-image-2 on an explicit equirectangular prompt. Evaluate the cell below to drop into the scene; drag and the polar regions stretch the way a real equirectangular does.
Heads up: the interactive cell above is fully draggable in desktop Mathematica or the Wolfram Player. The browser-side notebook viewer that powers Wolfram Community does not render its mouse interaction — you will see a static preview instead. Click here for a self-contained 360° browser viewer of this panorama (a Three.js page hosted on the Wolfram Cloud, opens in a new tab) that responds to click-and-drag and pinch-zoom natively.
6.2 The Moon, with Earthrise (synthetic, gpt-image-2)
6.2 The Moon, with Earthrise (synthetic, gpt-image-2)
Lunar surface in the Apollo style: grey regolith below you, distant Lunar mountains, the unfiltered jet-black star-flecked sky of a body with no atmosphere, and the blue-and-white Earth hanging large in the sky at one specific heading. Drag horizontally and the Earth swings in and out of view.
Heads up: the interactive cell above is fully draggable in desktop Mathematica or the Wolfram Player. The browser-side notebook viewer that powers Wolfram Community does not render its mouse interaction — you will see a static preview instead. Click here for a self-contained 360° browser viewer of this panorama (a Three.js page hosted on the Wolfram Cloud, opens in a new tab) that responds to click-and-drag and pinch-zoom natively.
6.3 Underwater coral reef (synthetic, gpt-image-2)
6.3 Underwater coral reef (synthetic, gpt-image-2)
A tropical reef in every direction: corals on the seabed below you (the nadir), schools of fish in the equatorial band, bright filtered sunlight from above at the zenith. The reef is the one panorama in the section that you could in principle have visited — it just happens to be a place that the Map Tiles API does not cover.
Heads up: the interactive cell above is fully draggable in desktop Mathematica or the Wolfram Player. The browser-side notebook viewer that powers Wolfram Community does not render its mouse interaction — you will see a static preview instead. Click here for a self-contained 360° browser viewer of this panorama (a Three.js page hosted on the Wolfram Cloud, opens in a new tab) that responds to click-and-drag and pinch-zoom natively.
6.4 Mars for real: a Perseverance rover panorama (NASA)
6.4 Mars for real: a Perseverance rover panorama (NASA)
For comparison: this is a genuine Mars panorama, stitched from the Perseverance rover's Navcam imagery on sol 1110 of the Mars 2020 mission. It is a real photograph (rather than a generative model's guess at one). The rover's own deck and arm are visible in the lower half of the panorama; the Jezero-crater terrain stretches around the horizon. Image credit: NASA/JPL-Caltech — in the public domain under 17 U.S.C. §105.
Heads up: the interactive cell above is fully draggable in desktop Mathematica or the Wolfram Player. The browser-side notebook viewer that powers Wolfram Community does not render its mouse interaction — you will see a static preview instead. Click here for a self-contained 360° browser viewer of this panorama (a Three.js page hosted on the Wolfram Cloud, opens in a new tab) that responds to click-and-drag and pinch-zoom natively.
7. Implementation notes
7. Implementation notes
8. References
8. References
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
StreetView360: draggable 360° panoramas using Google Maps street view tiles API
by Marco Thiel
Wolfram Community, STAFF PICKS, June 4, 2026
https://community.wolfram.com/groups/-/m/t/3727439
by Marco Thiel
Wolfram Community, STAFF PICKS, June 4, 2026
https://community.wolfram.com/groups/-/m/t/3727439