Note: as of May 2025 the code in this post does not work.
What works for photospheres is turning a photosphere viewing URL like:
https://www.google.com/maps/place/Borot+Lots+Campground/@30.5021229,34.6319275,3a,75y,315.58h,91.88t/data=!3m8!1e1!3m6!1sCIHM0ogKEICAgIDqy52-jAE!2e10!3e11!6shttps:%2F%2Flh3.googleusercontent.com%2Fgpms-cs-s%2FAB8u6HZTukqE-3smpL_xzpTY2oWZNf7zn4T9jQhVDBJ_TG-ZQWFgjvuo2jVKWya-CX4xEf7-6igY7SqslnHdxUxDlTxP7xlJRUKlDPxEtrJW5buM4pmHoaS-Uu3d-SemgpSD6Onfr3icog%3Dw900-h600-k-no-pi-1.8781544128473797-ya207.57962850748117-ro0-fo100!7i12800!8i3890!4m7!3m6!1s0x1501e72618987fe3:0x3f575221900fd9c6!8m2!3d30.5135718!4d34.6086344!10e5!16s%2Fg%2F11cnd55nkj?entry=ttu&g_ep=EgoyMDI1MDUwNi4wIKXMDSoASAFQAw%3D%3D
into this URL:
https://lh3.googleusercontent.com/gps-cs-s/AB8u6HZTukqE-3smpL_xzpTY2oWZNf7zn4T9jQhVDBJ_TG-ZQWFgjvuo2jVKWya-CX4xEf7-6igY7SqslnHdxUxDlTxP7xlJRUKlDPxEtrJW5buM4pmHoaS-Uu3d-SemgpSD6Onfr3icog=s8000-k-no
Here is how you can download imagery from Google Maps onto your own computer.
This method involves bookmarklets – special bookmarks that run custom javascript code on the page you are visiting. Steps:
- Choose the relevant bookmarklet from the 3 on this page
- Drag the (Button) next of the bookmarklet into the “Bookmarks” bar in your browser
- Visit the Google Streetview page with the image you want to download
- Press on the bookmarklet link you just added to your bookmarks
- The image/panorama will open in a new tab. Right-click on it and pick “Save Image As…”
Repeat steps 3 through 5 for as many images/photospheres/streetviews as you wish!
You can view your saved Photospheres/Streetview images at
https://arachnoid.com/3DViewer/index.html
or at
https://renderstuff.com/tools/360-panorama-web-viewer/
Download Individual Photos / Photospheres
Regular flat photos on Google Maps appear next to business listings and in the “explore” bar on the lower right:


User-uploaded Photospheres appear on Streetview as blue circles and only allow you to look around while standing in one spot:


The following Bookmarklet turns flat photos and user-uploaded photo-spheres into saveable images. Drag and drop this button to your Bookmarks bar:
Click to expand the readable code for this bookmarklet. It was converted to a link using Bookmarkleter.
let currentURL = window.location.href;
let panoId = currentURL.match(/!1s(.+?)!/)[1];
let newURL = "https://lh3.ggpht.com/p/" + panoId + "=s8000";
window.open(newURL, '_blank').focus();
Download a Streetview Sphere
Note: as of May 2025 the code in this post does not work. There is a photosphere workaround at the top of the page, but no workaround for Streetview.
Google Streetview images are the ones appearing as part of a “path” on Google Maps and that allow you to move around. They were captured by the Google Team and function differently than the sandalone user-uploaded Photospheres discussed higher on this page.

This is bookmarklet prepares Zoom level 4 Streetview panorama for saving as a flat image (with a fallback to Zoom level 3). Click and drag this button into your Bookmarks bar:
This is the readable code behind this bookmarklet.
// zoomLevel = zoom level of streetview. We start at 4 and recursively fail back to 3 from within this function if necessary
function downloadSphere( zoomLevel )
{
// grab panorama ID
var currentURL = window.location.href;
var panoId = currentURL.match(/!1s(.+?)!/)[1];
// maximum possible x and y values. For zoom level 4 in car view - we're fetching 128 tile images, each one 512x512 px
var max_x = 15;
var max_y = 7;
// actual x and y counts - in case sphere is not the max size
var actual_x = 0;
var actual_y = 0;
// create invisible canvas element - in our maximum hypothetical size
var canvas = document.createElement('canvas');
canvas.width = (max_x + 1) * 512;
canvas.height = (max_y + 1) * 512;
var context = canvas.getContext('2d');
// total number of images we're loading. will help us determine when all tiles are loaded
var allimages = (max_x+1) * (max_y+1);
// when we're done painting all the tiles to canvas, export it as an image into a new tab
function exportCanvas()
{
// hardcoded case: if x=0 and y=0 then fall back to zoom 3. There are also older spheres zoom 5 is available with 256x256 tiles, but we don't bother with that.
if( actual_x == 0 && actual_y == 0 )
{
//alert("No tiles retrieved at Zoom Level 4. Falling back to Zoom 3.")
return( downloadSphere(3))
}
//create our "final" canvas, potentially smaller than the hypothetical large canvas
var canvasCropped = document.createElement('canvas')
canvasCropped.width = (actual_x + 1) * 512
canvasCropped.height = (actual_y + 1) * 512
// hardcoded case for x=12 and y=6 grid - it has a black band running along the bottom that needs to be cropped
if( actual_x == 12 && actual_y == 6 ){ canvasCropped.height -= 256; }
// hardcoded case for x=6 and y=3 grid - 2007 sphere: it has a black band on the bottom and an extra column of tiles on the right
if( actual_x == 6 && actual_y == 3 ){ canvasCropped.height -= 384; canvasCropped.width -= 256; }
var contextCropped = canvasCropped.getContext('2d')
contextCropped.drawImage( canvas, 0, 0) // draw the contents of the first canvas into our cropped-size canvas
// Chrome-specific workaround: Chrome doesn't allow opening base64 URLs from code
var new_window = window.open();
new_window.document.body.appendChild( canvasCropped ) // will save the image as PNG, but it solves an intractable issue in Firefox. I suspect it was due to their 32MB Data URL limit
}
// The below code loads all the image tiles and composes them in a grid
// closures https://stackoverflow.com/questions/1552941/how-does-a-function-in-a-loop-which-returns-another-function-work
for( let x = 0; x <= max_x; x++ )
{
for( let y = 0; y <= max_y; y++ )
{
let img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://streetviewpixels-pa.googleapis.com/v1/tile?cb_client=maps_sv.tactile&panoid="+panoId+"&x="+x+"&y="+y+"&zoom="+zoomLevel+"&nbt=1&fover=2";
img.onload = function( x, y) { // must wait for the image to load before you try to draw it
return function()
{
//console.log("good x="+x+" y="+y)
context.drawImage(img, 512 * x, 512 * y);
// increment the "actual" x and y dimensions. That way we'll figure out the available number of tiles on the fly
if( x > actual_x ){ actual_x = x; }
if( y > actual_y ){ actual_y = y; }
allimages--;
if( allimages == 0 ) // this is the last tile to load - open the final image in new tab
{
//console.log("actual X: "+actual_x+" -- actual Y: "+actual_y)
exportCanvas() // create new tab with our canvas as an image
}
}
}(x,y);
// errors in loading are ok - just means we're trying to load a bigger image than actually exists
img.onerror = function(mysource){
return function()
{
//console.log("err x="+x+" y="+y)
allimages--; // do this so we generate an image even if it is missing tiles
if( allimages == 0 ) // this is the last tile to load - open the final image in new tab
{
//console.log("actual X: "+actual_x+" -- actual Y: "+actual_y)
exportCanvas()
}
}
}(img.src);
}
}
} // downloadSphere
downloadSphere( 4 )
I used Bookmarkleter to convert the code into a bookmarklet.
Leave a Reply