---
title: "How to take a map screenshot with Usersnap | JavaScript maps SDK"
description: "Take map screenshot with Usersnap integration using helper."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# How to take a map screenshot with Usersnap

This tutorial addresses the common issue of blank images (missing maps) appearing in screenshots instead of a beautiful map displays when using Usersnap reporting and feedback tool.

1.  Create a simple web page where we will add a map.
    
    ```html
    <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Maptiler screenshot</title>
         <script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
         <link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
         <style>
             body {
               margin: 60px 40px;
               font-family: Arial, sans-serif;
             }
             #map-container {
                 width: calc(100% - 80px);
                 height: calc(100vh - 120px);
                 position: relative;
                 margin: auto;
                 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
             }
             .maptiler-logo {
               position: absolute;
               top: 10px;
               left: 80px;
             }
         </style>
     </head>
     <body>
         <div class="maptiler-logo">
           <a href="https://www.maptiler.com/" target="_blank">
             <img src="https://www.maptiler.com/styles/style/logo/maptiler-logo-adaptive.svg" alt="MapTiler Logo">
           </a>
         </div>
         <div id="map-container"></div>
         <script>
             maptilersdk.config.apiKey = "YOUR_MAPTILER_API_KEY_HERE";
    
             const map = new maptilersdk.Map({
               container: document.getElementById("map-container"),
               style: maptilersdk.MapStyle.STREETS,
               geolocate: true,
             });
         </script>
     </body>
     </html>
    ```
    
2.  Insert your valid [MapTiler API key](https://cloud.maptiler.com/account/keys/) in place of `YOUR_MAPTILER_API_KEY_HERE`.
    
3.  Insert the Usersnap snippet. Copy this code into your webpage, right before the closing `</body>` tag or view the [Usersnap installation guide](https://help.usersnap.com/docs/installation-via-html)
    
    ```html
    <script>
       window.onUsersnapLoad = function(api) {
         api.init();
       };
       var script = document.createElement('script');
       script.defer = 1;
       script.src = 'https://widget.usersnap.com/global/load/YOUR-USERSNAP-SPACE-API-KEY?onload=onUsersnapLoad';
       document.getElementsByTagName('head')[0].appendChild(script);
     </script>
    ```
    
4.  Replace `YOUR-USERSNAP-SPACE-API-KEY` with your designated Usersnap Space API Key.
    
5.  Reload the page. Here is what the basic web page looks like:
    
    ![Basic web page with a map and feedback button](./webpage-map-feedback-button.webp)
    
6.  Get user feedback. Click the Feedback button to Report an issue. Thanks to the Feedback widget with screen capture, you can collect not only the feedback of your users but also take screenshots or screen recordings from their browsers.
    
7.  Utilize the integrated feedback tools to annotate the map by drawing relevant markings and complete the detailed issue submission form with pertinent information.
    
    ![Usersnap feedback report](./feedback-report-issue-form.webp)
    
8.  Click the Submit button to send your feedback.
    
9.  Review the user feedback. Access the Usersnap dashboard interface and select the specific issue report created during the previous step.
    
10.  Open the attached screenshot image. Sadly, you’ll notice the screenshot appears in the Usersnap dashboard without the map image (no map image). This is how the screenshot looks in the Usersnap dashboard:
     
     ![Usersnap dashboard feedback report](./feedback-blank-map-image.webp)
     
11.  Make the rendering buffer available. Replace the original `.toDataURL()` of the map canvas with a custom implementation.
     
     ```js
     const map = new maptilersdk.Map({
        container: document.getElementById("map-container"),
        style: maptilersdk.MapStyle.STREETS,
        geolocate: true
      });
     
      // Explicitely triggering a redraw of the map
      map.redraw();
     
      const mapCanvas = map.getCanvas();
     
      // This will contain the frame data,
      // and will be replaced at every idle event
      let lastIdleDataURL = "";
      // We keep the original .toDataURL method because we still
      // need to call it!
      // (dont't forget to bind it)
      const originalToDataURL = mapCanvas.toDataURL.bind(mapCanvas);
      // Replacing the original .toDataURL() of the map canvas with a fake one that
      // returns the latest idle frame data.
      // The fake version is now the one being called by Usersnap.
      mapCanvas.toDataURL = function(type, encoderOptions) {
           
        return lastIdleDataURL;
      }
      // Waiting for the next moment, just after redraw, 
      // when the GPU will not be computing a new frame
      // When the map is idle, we get the dataURL to be stored for later.
      // Note how we are using the "originalToDataURL" function, 
      // since it's the one that does the actual frame grabbing
      map.on("idle", async () => {
        lastIdleDataURL = originalToDataURL();
      });
     ```
     
12.  Create an issue report using the feedback button.
     
13.  Access the Usersnap dashboard and locate your newly created issue report.
     
14.  View the attached screenshot image to confirm the successful capture of the map image. Now you have the map image in the report.
     
     ![Usersnap dashboard feedback report with a map image](./feedback-map-image.webp)
     

### Complete source code

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Maptiler screenshot</title>
  <script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
  <link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
  <style>
    body {
      margin: 60px 40px;
      font-family: Arial, sans-serif;
    }
    #map-container {
      width: calc(100% - 80px);
      height: calc(100vh - 120px);
      position: relative;
      margin: auto;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    }
    .maptiler-logo {
      position: absolute;
      top: 10px;
      left: 80px;
    }
  </style>
</head>
<body>
  <div class="maptiler-logo">
    <a href="https://www.maptiler.com/" target="_blank">
      <img src="https://www.maptiler.com/styles/style/logo/maptiler-logo-adaptive.svg" alt="MapTiler Logo">
    </a>
  </div>
  <div id="map-container"></div>
  <script>
    maptilersdk.config.apiKey = "YOUR_MAPTILER_API_KEY_HERE";

    const map = new maptilersdk.Map({
      container: document.getElementById("map-container"),
      style: maptilersdk.MapStyle.STREETS,
      geolocate: true,
    });

    // Explicitely triggering a redraw of the map
    map.redraw();

    const mapCanvas = map.getCanvas();

    // This will contain the frame data,
    // and will be replaced at every idle event
    let lastIdleDataURL = "";
    // We keep the original .toDataURL method because we still
    // need to call it!
    // (dont't forget to bind it)
    const originalToDataURL = mapCanvas.toDataURL.bind(mapCanvas);
    // Replacing the original .toDataURL() of the map canvas with a fake one that
    // returns the latest idle frame data.
    // The fake version is now the one being called by Usersnap.
    mapCanvas.toDataURL = function(type, encoderOptions) {

      return lastIdleDataURL;
    }
    // Waiting for the next moment, just after redraw,
    // when the GPU will not be computing a new frame
    // When the map is idle, we get the dataURL to be stored for later.
    // Note how we are using the "originalToDataURL" function,
    // since it's the one that does the actual frame grabbing
    map.on("idle", async () => {
      lastIdleDataURL = originalToDataURL();
    });
  </script>
  <script>
    window.onUsersnapLoad = function(api) {
      api.init();
    };
    const script = document.createElement('script');
    script.defer = 1;
    script.src = 'https://widget.usersnap.com/global/load/YOUR-USERSNAP-SPACE-API-KEY?onload=onUsersnapLoad';
    document.getElementsByTagName('head')[0].appendChild(script);
  </script>
</body>
</html>
```

## Learn more

If you want to know the reasons why these feedback tools return a blank image and why this implementation approach was necessary, you can find full technical details in [How to fix a missing map from feedback button](https://docs.maptiler.com/sdk-js/examples/helper-screenshot-feedback/).

## Related examples

### [Download a map screenshot (screenshot helper)](https://docs.maptiler.com/sdk-js/examples/helper-screenshot-download/)

Examples

Download map screenshot as PNG file using helper.

### [Take screenshot (screenshot helper)](https://docs.maptiler.com/sdk-js/examples/helper-screenshot/)

Examples

Capture map view as PNG blob using helper.

### [Missing map from feedback button](https://docs.maptiler.com/sdk-js/examples/helper-screenshot-feedback/)

Tutorials

Fix missing map in feedback using screenshot helper.

### [Screenshot with Ybug](https://docs.maptiler.com/sdk-js/examples/helper-screenshot-ybug/)

Tutorials

Take map screenshot with Ybug integration using helper.
