October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
CORS

How to Fix Grey Leaflet Map Captures with MapKit JS and dom-to-image

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The usual cause is canvas security, not Leaflet styling. Your tiles can be visible in the browser while a DOM-to-image export turns the map grey because the tile images came from another origin without permission for pixel read-back. Confirm the tile response headers, request tiles in CORS mode, and capture only after all tiles finish loading. If the provider does not permit CORS, use an authorized same-origin proxy or a provider that does.

First identify which map and capture path you actually have

Leaflet and MapKit JS are different frameworks. A page may contain both, but MapKit JS documentation about cross-origin image sources does not establish a Leaflet-plus-dom-to-image fix. Before changing code, record:

  • The map framework that owns the tiles: Leaflet, MapKit JS, or another layer.
  • The exact capture package and version. dom-to-image, dom-to-image-more, and html2canvas have different option names and behavior.
  • The tile URL, response status, Access-Control-Allow-Origin header, and any required authorization or referrer.
  • Whether the grey result is produced before tiles finish loading or after an origin-policy error appears in the console.

A grey export can therefore be a failed request, a CORS denial, or a timing race. Treat those as separate tests.

Why a visible map can become a grey canvas

Browsers allow an image from another origin to be displayed in many situations. Reading those pixels back through a canvas is more restricted. As html2canvas documents, drawing an image outside the page’s origin can taint the canvas, making it unreadable for export operations. A DOM reconstruction library also does not take a native screenshot; it rebuilds an image from the DOM, so the result may differ from what the browser visibly paints.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

Leaflet’s TileLayer crossOrigin setting asks the browser to load tiles in a mode suitable for pixel access. It cannot add a permissive header to the tile server’s response. The server must opt in for your requesting origin. Likewise, an option such as html2canvas’s useCORS requests CORS loading; it does not override server policy.

Use DevTools to classify the failure

  1. Open the browser’s developer tools and select Network.
  2. Reload the page and filter for representative tile requests (often URLs ending in .png, .jpg, or .webp).
  3. Check that each request returns an image, not a login page, rate-limit response, or error document.
  4. Inspect response headers for Access-Control-Allow-Origin. It must allow the origin from which your page is served (or use an appropriate non-credentialed wildcard where the provider permits it).
  5. Watch the Console for CORS, tainted-canvas, mixed-content, or authorization errors.
  6. In the Leaflet map, listen for tile lifecycle events and verify that the visible tile set has completed before starting the export.

If a tile request fails, fix its URL, credentials, referrer policy, quota, or provider terms first. If requests succeed but the console reports blocked pixel access, solve CORS. If both are clean and the export is blank only intermittently, solve readiness timing.

Configure Leaflet for CORS-aware tiles

Set crossOrigin when creating the tile layer, using the value expected by your provider. The setting must be present before tiles are requested:

const map = L.map('map').setView([37.7749, -122.4194], 12);

const tiles = L.tileLayer('https://tiles.example.com/{z}/{x}/{y}.png', {
  crossOrigin: true,
  attribution: '© Tile provider'
}).addTo(map);

Some providers document a string value such as 'anonymous' rather than a Boolean. Use the form documented by that provider and by your installed Leaflet version. Do not put secret API keys in a public tile URL unless the provider explicitly designs those keys for browser use.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Now verify the response itself. A client-side attribute cannot manufacture Access-Control-Allow-Origin. If the provider omits the header or rejects your origin, changing Leaflet options alone cannot make the canvas readable.

Wait for tiles before invoking the capture

Capturing immediately after constructing the map can produce an empty or partly grey result even when CORS is correct. Use the map’s lifecycle rather than an arbitrary short delay. For a single view, a tile-load listener is a better starting point:

function waitForTiles(layer) {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      layer.off('load', onLoad);
      reject(new Error('Tile layer did not finish before timeout'));
    }, 30000);

    function onLoad() {
      clearTimeout(timeout);
      layer.off('load', onLoad);
      resolve();
    }

    layer.once('load', onLoad);
  });
}

await waitForTiles(tiles);
// Start your dom-to-image call here.

For maps that pan, zoom, or load additional imagery, wait after the final view change and confirm that no relevant tile requests remain pending. A delay can hide a race, but it cannot repair a CORS denial.

Use the capture library’s own CORS settings

When the project uses html2canvas

html2canvas exposes useCORS: true to attempt CORS image loading. It also documents a proxy route for a same-origin proxy design. Its defaults and option names belong to html2canvas; do not copy them into dom-to-image without checking that package’s documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.
const canvas = await html2canvas(document.querySelector('#map'), {
  useCORS: true,
  backgroundColor: null
});
const png = canvas.toDataURL('image/png');

allowTaint: true is not an export fix. It may allow a foreign image to be drawn, but a tainted canvas remains unreadable for operations such as toDataURL() or pixel extraction.

When the project uses dom-to-image

Inspect the installed package’s documentation and source for its exact image-loading and cache-busting options. The evidence for html2canvas’s names does not establish equivalent dom-to-image options. If dom-to-image cannot load your tiles with the required CORS semantics, switching options blindly will not help; solve the server response or choose a capture path that supports it.

Same-origin proxy: useful, but only when authorized

A proxy can fetch tiles server-side and serve them from the same origin as your application. This avoids the browser’s cross-origin read-back restriction only when the proxy is lawful, secured, and correctly configured. Confirm the tile provider’s terms, preserve appropriate caching and content headers, and keep private credentials on your server.

  • Allow only approved tile hosts; never create an unrestricted public image proxy.
  • Apply request timeouts, size limits, rate limits, and response-type checks.
  • Do not expose provider tokens in client JavaScript or proxy URLs.
  • Return an image with the correct content type and, if needed, cache headers.
  • Keep attribution and usage requirements visible in the map and export.

If the provider does not authorize proxying, select a tile source that documents browser CORS support instead.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

MapKit JS considerations

MapKit JS image-source guidance addresses CORS for cross-origin images used by MapKit JS. It does not prove that MapKit JS changes how Leaflet tiles are requested or that it fixes a Leaflet/dom-to-image export. If your page includes both frameworks, debug the image source actually consumed by the failing map. For a MapKit JS overlay, apply Apple’s documented image-source requirements; for a Leaflet layer, apply Leaflet’s tile and provider requirements independently.

When leaflet-image is a better fit

leaflet-image is an export-oriented alternative, not a universal replacement. Its documented constraints include:

  • Tile and marker image sources must support CORS.
  • Leaflet 1.x vector layers intended for export need Canvas rendering rather than SVG.
  • HTML map elements such as controls and HTML-based markers are not rasterized by the library.

Choose it when your map consists of export-compatible tiles, Canvas vectors, and image markers. Keep DOM-based capture when you need surrounding page HTML, controls, or custom overlays, and accept that reconstruction may not exactly match the live rendering.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Complete diagnostic example

const map = L.map('map').setView([40.7128, -74.0060], 11);
const layer = L.tileLayer('https://tiles.example.com/{z}/{x}/{y}.png', {
  crossOrigin: 'anonymous',
  attribution: '© Tile provider'
}).addTo(map);

function waitForLayer(layer, ms = 30000) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      layer.off('load', done);
      reject(new Error('Timed out waiting for tiles'));
    }, ms);
    function done() {
      clearTimeout(timer);
      layer.off('load', done);
      resolve();
    }
    layer.once('load', done);
  });
}

await waitForLayer(layer);

// Use the options documented by your installed capture package.
const node = document.querySelector('#map');
const blob = await domtoimage.toBlob(node /* package-specific options */);
const link = document.createElement('a');
link.download = 'map.png';
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);

If this still fails, return to the Network and Console checks. The remaining cause is usually a missing response header, a provider authentication rule, an unsupported dom-to-image option, or a map element that the chosen library cannot reconstruct.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Performance, reliability, and security notes

  • Full-page or high-retina exports increase memory use; capture the map element when that is all you need.
  • Reuse a loaded map for repeated exports, but wait after every pan or zoom.
  • Set an explicit timeout and surface a useful error instead of downloading a grey file silently.
  • Keep attribution in the rendered map and check provider limits before batch exports.
  • Test production origins, HTTPS, authentication, and content-security policy; localhost success does not prove deployment success.
  • Do not treat a successful visual display as proof that pixel read-back is permitted.

Common errors and fixes

Symptom Likely cause Fix
Grey map, CORS error in console Tile response does not allow your origin Use a provider with suitable CORS, or an authorized same-origin proxy.
Blank or partial map, no CORS error Capture started before tiles loaded Wait for the tile layer’s load lifecycle and final view.
Images display but toDataURL throws Canvas is tainted Fix server CORS; allowTaint does not make pixels readable.
Changing useCORS has no effect Project uses dom-to-image, not html2canvas Use the installed package’s documented options or change capture approach.
Vectors or controls missing with leaflet-image Unsupported SVG or HTML content Render vectors on Canvas and replace or separately render HTML elements.
Tiles return 401, 403, or HTML Bad credentials, referrer, quota, or URL Inspect the response and provider requirements; keep secrets server-side.

Or skip the browser setup

ScreenshotNeo captures a URL through an API, so you do not need to make a browser DOM-to-image pipeline handle tile CORS. Before capture it accepts the cookie or consent banner as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

Use the same one-call API for a rendered page:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for options such as full-page capture, selector capture, custom CSS and JavaScript, waits, blocking rules, device and retina settings, PDF output, signed links, async jobs, bulk capture, and caching. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Frequently Asked Questions

Does adding crossOrigin guarantee a non-grey export?

No. It changes the browser’s request mode, but the tile server must return a header permitting your page’s origin.

Can a longer timeout fix a CORS error?

No. Waiting helps only when the capture began before tiles loaded; it cannot change an origin-policy decision.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is MapKit JS required to capture a Leaflet map?

No. They are separate frameworks. Debug the framework that owns the failing map and its image sources.

Why does the live map look correct while the export fails?

Displaying a cross-origin image and reading its pixels through a canvas are governed by different browser security rules.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.