Google Street View in CesiumJS
CesiumJS supports the display of panoramic imagery in both equirectangular and cube map formats, enabling panoramas to be accurately positioned and oriented alongside other geospatial content within a 3D scene.
Panoramic imagery can be integrated into CesiumJS using external providers or custom datasets. In this tutorial, you will learn how to load Google Street View imagery via the Google Street View Static API and incorporate it directly into your CesiumJS scenes.

Google Street View in CesiumJS, at Lombard Street in San Francisco, California, USA.
You’ll learn how to:
- Initialize a CesiumJS viewer.
- Add Google Photorealistic 3D Tiles for spatial context.
- Configure access to the Google Street View Static API via Cesium ion.
- Fetch the nearest Street View panorama for a given location.
- Load that panorama into the CesiumJS scene.
- Allow users to change locations by editing coordinates.
- Toggle Photorealistic 3D Tiles on and off for comparison.
Before starting, make sure you have:
- A CesiumJS application set up (local dev server or Sandcastle-style environment).
- A valid Cesium ion access token assigned to
Cesium.Ion.defaultAccessToken. - Access enabled for Google Photorealistic 3D Tiles and Google Street View through Cesium ion.
Start by importing CesiumJS and Sandcastle utilities; then create a basic viewer. For this example, you will disable UI elements that are not needed and hide the globe because Street View panoramas are rendered as local scene primitives.
import * as Cesium from "cesium";
import Sandcastle from "Sandcastle";
const viewer = new Cesium.Viewer("cesiumContainer", {
selectionIndicator: false,
infoBox: false,
});
viewer.scene.globe.show = false;
At this point, you have a minimal CesiumJS scene ready to accept 3D content.
Photorealistic 3D Tiles provide valuable spatial context and make it easy for you to compare Street View imagery with the surrounding 3D environment.
let tileset;
try {
tileset = await Cesium.createGooglePhotorealistic3DTileset({
// Only the Google Geocoder can be used with Google Photorealistic 3D Tiles.
onlyUsingWithGoogleGeocoder: true,
});
viewer.scene.primitives.add(tileset);
} catch (error) {
console.log(`Error loading Photorealistic 3D Tiles tileset.\n${error}`);
}
This tileset is optional for Street View itself but extremely useful for orientation and comparison.
Sandcastle.addToolbarButton("Toggle Photorealistic Tiles", function () {
tileset.show = !tileset.show;
});
This makes it easy for you to visually compare Street View imagery with the surrounding 3D context.
Connect to Cesium ion to enable loading Google Street View panoramic images without needing your own Google Maps API credentials. This avoids hardcoding API keys in your application.
Loading Google Street View panoramic images via Cesium ion is configured for development purposes only. To build your own application, you should obtain and use your own Google Maps API credentials.
const ionResponse = await Cesium.Resource.fetchJson({
url: `${Cesium.Ion.defaultServer}/experimental/panoramas/google`,
headers: {
Authorization: `Bearer ${Cesium.Ion.defaultAccessToken}`,
},
});
Cesium.GoogleMaps.defaultStreetViewStaticApiKey = ionResponse.options.key;
Cesium.GoogleMaps.streetViewStaticApiEndpoint = ionResponse.options.url;
Once configured, CesiumJS can request Street View imagery on your behalf.
The GoogleStreetViewCubeMapPanoramaProvider handles fetching and assembling Street View imagery into a cube map suitable for real-time rendering.
const provider = await Cesium.GoogleStreetViewCubeMapPanoramaProvider.fromUrl();
This provider will be reused for all panorama requests in the scene.
You do not need to pass a URL to GoogleStreetViewCubeMapPanoramaProvider.fromUrl().
By default, it uses Cesium.GoogleMaps.streetViewStaticApiEndpoint, which is set automatically when configuring Street View access through Cesium ion. If this value is not explicitly overridden, it defaults to Google’s standard Static Street View API endpoint.
Next, you will define a helper function that takes a panorama ID and location, loads the panorama, adds it to the scene, and positions the camera inside it.
async function loadPanorama(panoIdObject) {
const { panoId, latitude, longitude } = panoIdObject;
const panoCartographic = Cesium.Cartographic.fromDegrees(
longitude,
latitude,
0,
);
const streetViewPanorama = await provider.loadPanorama({
cartographic: panoCartographic,
panoId,
});
viewer.scene.primitives.add(streetViewPanorama);
const lookPosition = Cesium.Cartesian3.fromDegrees(
longitude,
latitude,
0,
);
const heading = Cesium.Math.toRadians(-90);
viewer.scene.camera.lookAt(
lookPosition,
new Cesium.HeadingPitchRange(
heading, // heading
0, // pitch
2, // range
),
);
}
This function is the core of the Street View integration.
A panorama with both Street View and Photorealistic 3D Tiles.
Street View experiences typically allow rotation and tilt but restrict translation and zoom. You can match that behavior using the screen space camera controller and implement scroll-wheel zoom by adjusting the camera’s field of view.
const controller = viewer.scene.screenSpaceCameraController;
controller.enableRotate = true;
controller.enableTilt = true;
controller.enableTranslate = false;
controller.enableZoom = false;
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
const minFov = Cesium.Math.toRadians(20.0);
const maxFov = Cesium.Math.toRadians(100.0);
const zoomSpeed = 0.05;
handler.setInputAction(function (wheelDelta) {
const camera = viewer.camera;
const frustum = camera.frustum;
let fov = frustum.fov;
if (wheelDelta < 0) {
fov *= 1.0 + zoomSpeed;
} else {
fov *= 1.0 - zoomSpeed;
}
frustum.fov = Cesium.Math.clamp(fov, minFov, maxFov);
}, Cesium.ScreenSpaceEventType.WHEEL);
This keeps the user anchored inside the panorama while still allowing intuitive mouse-wheel zooming and free exploration, closely matching the Google Street View interaction model.
Finally, you will define an initial location, find the nearest Street View panorama, and load it into the scene.
// User-editable location
const longitude = -75.222071;
const latitude = 40.027237;
const height = 1; // meters
const cartographic = Cesium.Cartographic.fromDegrees(
longitude,
latitude,
height,
);
const panoIdObject = await provider.getNearestPanoId(cartographic, 100);
loadPanorama(panoIdObject);
To explore a new location in this tutorial, you need only to update the longitude and latitude values and reload the application.
Explore and experiment with the Google Street View panorama Sandcastle.
No panorama loads for a location
Not all coordinates have Street View coverage. If getNearestPanoId returns undefined or throws an error, try:
- Increasing the search radius (the second argument to
getNearestPanoId). - Using a location known to have Street View coverage, such as a major city or road.
Panoramas fail to load
This is typically caused by missing or misconfigured credentials. Verify that:
- Your Cesium ion access token is valid.
- You have called Cesium ion
/experimental/panoramas/googleendpoint and used the results to set thedefaultStreetViewStaticApiKeyandstreetViewStaticApiEndpointbefore creating the provider.
Photorealistic 3D Tiles do not appear
If the Photorealistic 3D Tiles fail to load:
- Confirm that Google Photorealistic 3D Tiles are enabled in Cesium ion.
- Ensure the viewer is configured to use the Google geocoder.
- Check the browser console for authorization or network errors.
Camera behaves unexpectedly
If the camera moves outside the panorama or behaves more like a globe view:
- Confirm that globe rendering is disabled (
viewer.scene.globe.show = false). - Ensure translation and zoom are disabled on the camera controller.
- Google Street View Cesium documentation: API reference for loading Google Street View imagery into CesiumJS panoramas via
GoogleStreetViewCubeMapPanoramaProvider - CesiumJS cube map panorama documentation: API reference for displaying a six-face cube map panorama in a CesiumJS scene
- Google Photorealistic 3D Tiles in CesiumJS: details for enabling, loading, and styling Google Photorealistic 3D Tiles dataset
- Google Street View CesiumJS Sandcastle: interactive example and live code playground for experimenting with Google Street View in CesiumJS along with other CesiumJS features
- Panoramic imagery in CesiumJS: overview of how equirectangular and cube map panoramas are rendered and positioned in CesiumJS
- CesiumJS documentation: core API reference and guides for building 3D geospatial applications with CesiumJS
- Cesium ion documentation: managing access tokens, assets, and third-party data integrations
- Introducing panoramic imagery in CesiumJS
In this tutorial, you learned how to integrate Google Street View imagery into a CesiumJS scene, position it accurately in 3D space, and compare it directly with Google Photorealistic 3D Tiles. This approach enables immersive, street-level visualization while retaining the full power of CesiumJS’s 3D geospatial rendering pipeline.
From here, you can extend this example by adding UI-driven location search or panorama navigation or blending Street View with additional 3D datasets.