Google Maps: “This page can't load Google Maps correctly”
The map turns dark, says “For development purposes only”, and a box asks “Do you own this website?”. The console of the browser names the reason. Each code below comes with its fix in the Google Cloud console, followed by what a map without Google costs.
What you see
The Maps JavaScript API shows one of two things when it refuses to load:
This page can't load Google Maps correctly. Do you own this website? OK
After you click OK, the map stays dark or grey with “For development purposes only” written across it. On some sites the map area says instead:
Oops! Something went wrong. This page didn't load Google Maps correctly. See the JavaScript console for technical details.
Neither text says why. Open the developer tools of the browser (F12), tab Console, and reload. Look for a line such as:
Google Maps JavaScript API error: RefererNotAllowedMapError https://developers.google.com/maps/documentation/javascript/error-messages#referer-not-allowed-map-error
The error codes
From the error reference of Google, most common first:
| Error | Meaning | Fix |
|---|---|---|
RefererNotAllowedMapError | The page is not among the websites the key allows. | Add the site to the website restrictions of the key (below). |
ApiNotActivatedMapError | The Maps JavaScript API is not enabled in the project of the key. | APIs & Services → Library → Maps JavaScript API → Enable. |
BillingNotEnabledMapError | The project has no billing account. | Link a billing account to the project. Google requires one even for use within the free amount. |
ApiTargetBlockedMapError | The API restrictions of the key leave out the Maps JavaScript API. | Add it to the allowed APIs of the key. |
InvalidKeyMapError | Google does not know the key. | Copy the key again from Credentials; check for spaces and missing characters. |
MissingKeyMapError | The script URL has no key parameter. | Load https://maps.googleapis.com/maps/api/js?key=YOUR_KEY. |
ExpiredKeyMapError | The key has expired or is not active yet. | Wait a few minutes after creating it, or create a new one. |
DeletedApiProjectMapError | The project of the key was deleted. | Create a new project and key. |
OverQuotaMapError | A quota of the project is used up. | Raise the quota in the console, or wait for the reset. |
RefererDeniedMapError | Google blocked the app for a breach of its terms. | Use the appeal form in the error reference. |
InvalidClientIdMapError | A client ID was used; client IDs can no longer be used since 31 May 2026. | Switch to an API key. |
Changes to a key take a few minutes to apply. Reload with an empty cache before you change anything else.
Website restrictions that work
Under APIs & Services → Credentials → your key → Application restrictions → Websites, every address the map runs on needs an entry. The safe set for one domain is two entries:
https://example.com/* https://*.example.com/*
Add staging hosts and the address you develop on as well. A page opened from a file (file:///) sends no website, so a restricted key cannot work there; use a local web server.
If the console shows no Google error
- A content security policy blocks the script. The console then says that loading
maps.googleapis.comviolates the policy; allow it inscript-src, and the image and connect sources that Google lists. - An ad blocker or privacy add-on blocks the request. Try a private window without add-ons.
- The map element has no height, so the map is there but 0 pixels high:
#map { height: 480px; }. - The
callbackin the script URL names a function that does not exist yet when the script loads.
What the map costs
Since March 2025 Google gives each SKU a free monthly amount instead of the former USD 200 credit. Dynamic Maps (the Maps JavaScript API) is an Essentials SKU with 10,000 free map loads a month; beyond that, the first tier costs USD 7 per 1,000 loads (prices from the Google price list, October 2026). A map load is counted when a page creates a map, whatever the visitor does with it afterwards.
Tile services count tiles instead. A map view loads about 15 to 30 tiles when it opens and more when people pan and zoom; with 30 to 50 tiles per view, 2 million tiles are 40,000 to 66,000 views.
| Example: 50,000 map views a month | Cost per month |
|---|---|
| Google Maps JavaScript API | 40,000 billed loads × USD 7 per 1,000 = about USD 280 |
| MapLibre with overpass.ch tiles | 1.5 to 2.5 million tiles: Maps Small (2 million tiles) for CHF 9, or Maps Medium for CHF 29 if visitors pan a lot |
An estimate with stated assumptions; the tiles per view depend on the size of the map and on how people use it. Your dashboard shows the real number after a day.
A map without Google
If the page needs a map with markers and nothing else from Google, MapLibre GL JS with a tile service needs no billing account. The code is short:
// Google Maps const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 47.37, lng: 8.54 }, zoom: 14 }); new google.maps.Marker({ position: { lat: 47.37, lng: 8.54 }, map, title: "Zurich" }); // MapLibre GL JS const map = new maplibregl.Map({ container: "map", style: "https://api.overpass.ch/v1/YOUR_KEY/maps/styles/light.json", center: [8.54, 47.37], // longitude first zoom: 13 // one less than in Google Maps for the same scale }); new maplibregl.Marker().setLngLat([8.54, 47.37]) .setPopup(new maplibregl.Popup().setText("Zurich")).addTo(map);
Three things change: coordinates are [longitude, latitude], zoom levels are one lower for the same scale, and the style URL replaces the map type. What does not come along: Places, Street View, Directions and the business listings of Google. If you need those, keep Google for them. For search and routing on open data there are services such as Nominatim and OSRM.
The map tiles of overpass.ch come from OpenStreetMap data, with nine styles and labels in 41 languages. A key of the type “Maps only” works like a Google key with website restrictions: limit it to your sites and a copy is useless elsewhere.
Try the map first
100'000 map tiles a month are free, with no credit card and no billing account. When the allowance is used up, tiles get HTTP 429 until the next month; we never bill overage.