I have tiles generated by Maperitive from an OSM file, and there's a nice tiles.json generated with them which specifies neatly the tiles-path, bounding box, minzoom, maxzoom, center, etc. The format is identical to the tileJSON specification given here: https://www.mapbox.com/guides/an-open-platform/#tilejson

But it just blows that the example stopped a step short and inline'd the JSON code into the example's source code, hence rendering it (pun intended) useless. No clue on https://github.com/mapbox/tilejson-spec either. All web searches for this lead to these sites; the rest digress into GeoJSON which is something else entirely. Why in the world would anyone go through the trouble of using JSON if one wasn't importing it from an external file? (no, please don't try to answer that.. it's not the main question. Focus!)

So, a humble request: Please re-write this example code given on mapbox.com, to show an external JSON file being loaded. (And please put in a word with someone there if you know them to post a proper example on the website)

<!DOCTYPE html>
  <meta charset=utf-8 />
  <script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.js'></script>
  <link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.css' rel='stylesheet' />
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
<div id='map' class='map'> </div>
L.mapbox.accessToken = '<your access token here>';
var tilejson = {
  "tiles": [ "https://api.tiles.mapbox.com/v4/examples.map-i86l3621/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoidHJpc3RlbiIsImEiOiJuZ2E5MG5BIn0.39lpfFC5Nxyqck1qbTNquQ" ],
  "minzoom": 0,
  "maxzoom": 18
L.mapbox.map('map', tilejson, {
    scrollWheelZoom: false
}).setView([43.6519,-79.3852], 15);

Edit: Included jquery.min.js and changed code as advised; am getting a "not well-formed" error in console. I reckon jquery doesn't like tileJSON. This is why full examples ought to be given :P. Please see and advise what needs to change here. Is there a more generic JSON-loader we can use instead of jquery? I believe we're very close to getting this.

var tilejson;
$.getJSON('pune/tiles.json', function(data) {
  tilejson = data;

L.mapbox.map('map', tilejson, {
    scrollWheelZoom: false

Here is the content of tiles.json (loading local tiles, generated by Maperitive; tested to be valid JSON as per http://codebeautify.org/jsonviewer):

    "tilejson": "1.0.0",
    "name": "Pune 1 to 16",
    "description": "Made with Maperitive",
    "attribution": "Map data © OpenStreetMap contributors",
    "tiles": [
    "minzoom": 1,
    "maxzoom": 16,
    "bounds": [
    "center": [

3 Answers 3


The reason you are getting a "not well formed" error in console is because your tilejson file loads asynchronously, meaning the script continues to execute while the tilejson object is only partly loaded as an incomplete promise object. So when you pass your tilejson object to L.mapbox.map, you are actually passing a promise object (which it can't parse).

So initialize your map in the success callback function that $.getJSON() provides. Like so:

$.getJSON('<url to tilejson>', function(tilejson) {
  L.mapbox.accessToken = 'pk.eyJ1IjoiamFtZXMtbGFuZS1jb25rbGluZyIsImEiOiJ3RHBOc1BZIn0.edCFqVis7qgHPRgdq0WYsA';
  var map = L.mapbox.map('map', tilejson, {
    scrollWheelZoom: false

However, you might still run into problems (e.g. w/ retina screens as outlined in my other answer) because L.mapbox.map makes some expectations that the tilejson is coming from MapBox's own server. For a more reliable solution, try something like this:

$.getJSON('<url to tilejson>', function(tilejson) {
  L.mapbox.accessToken = 'pk.eyJ1IjoiamFtZXMtbGFuZS1jb25rbGluZyIsImEiOiJ3RHBOc1BZIn0.edCFqVis7qgHPRgdq0WYsA';
  var map = L.mapbox.map('map', undefined, {
    layers: L.tileLayer(tilejson.tiles[0]),
    center: tilejson.center.slice(0,2).reverse(),
    zoom: tilejson.center[2],
    minzoom: tilejson.minzoom,
    maxzoom: tilejson.maxzoom,
    scrollWheelZoom: false
  • Thanks James. I'm not fixed on Leaflet of course.. using the Mapbox code to deliver the map is definitely an option. I just found Leaflet easiest to figure out so far. However, the use-case commands : 1. Everything open-source and free; 2.Completely offline. That accessToken thing has been scaring me away from Mapbox. Would it be OK to drop that, or deploy with the same token that you have provided without fear?
    – Nikhil VJ
    Jan 16, 2015 at 5:47
  • @nikhilvj It shouldn't really matter if you use mapbox.js or leaflet.js. leaflet doesn't have an option to pass tilejson to the L.map constructor, and while mapbox.js does, as I mentioned mapbox.js makes some (or at least one) assumptions that the tilejson is coming from mapbox servers. So would recommend loading your tilejson and passing the relevant values as options to the map constructor, which should work more-or-less the same for either leaflet's L.map or mapbox's L.mapbox.map . Jan 16, 2015 at 15:09
  • (as for the access token, I don't know if it's needed b/c you are loading tiles from your own service--not mapbox's. experiment w/ including it or not) Jan 16, 2015 at 15:12
  • ...also, if you are unsure of whether to go w/ mapbox.js or leaflet.js (and I don't think it's a big question, they are both pretty similar/would likely work just as well), compare the documentation for each, particularly the map constructor: L.map and L.mapbox.map. Jan 16, 2015 at 15:15
  • Is it still working? Please, can you provide a jsfiddle for this? :)
    – pnz1337
    Nov 29, 2019 at 10:20

Last time I tried to pass tileJSON directly to the L.mapbox.map constructor, I ran into issues when mapbox.js tried to automatically load retina tiles from my non-mapbox tileserver. If you are using a retina device, could point to your problem. If not, might cause additional problems after you've fixed your current issue. Check your console to see if you are getting 404 errors, something like:

GET http://<your tile url>/5/17/[email protected] 404 (Not Found)

mapbox automatically appends @2x when a request is made from a retina device.

When you load your JSON, if you still run into issues passing it directly to L.mapbox.map, you can always pass it's individual parts as options, similar to how you would work with leaflet's L.map. E.g.:

L.mapbox.map('map', undefined, { layers: L.tileLayer(tileJSON.tiles[0]), minZoom: tileJSON.minzoom, maxZoom: tileJSON.maxzoom });

  • Hi.. no, there ain't no retina device here for miles around. This use case is for off-the-internet schools in third world countries. Think "junked CRTs". It's dead-simple tiles here, loading on open-source browsers like Firefox, over a local LAN. JQuery is simply refusing to even load the JSON at this point. ("not well-formed"). The "when you load your JSON" stage is what needs to be solved first. I'm sure that tiles[0] command will work once that happens. Please give a full example demonstrating the JSON being loaded successfully.
    – Nikhil VJ
    Jan 15, 2015 at 15:12
  • Please just paste your code from the Last time I tried to pass tileJSON directly to the L.mapbox.map constructor >> that's what I'm looking for and just not being able to find around here. Full code! (of course, the JSON better be coming from an external JSON file.. not something inline)
    – Nikhil VJ
    Jan 15, 2015 at 15:19

I would use getJSON() from the jquery library:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

var tilejson;
$.getJSON('/path/to/your.json', function(data) {
  tilejson = data;
  • Thanks. What's the jquery .js URL.. have a to include the script up at the top, right?
    – Nikhil VJ
    Jan 13, 2015 at 19:54
  • Edited answer to provide jquery cdn link
    – jmcbroom
    Jan 13, 2015 at 20:08
  • Blended this in.. I'm getting a "not well formed" error in console. Adding the new code in the question, please see and tell what needs fixing.
    – Nikhil VJ
    Jan 14, 2015 at 7:38
  • Try jsonlint. It might help point out any issues with your tileJSON. Jan 14, 2015 at 14:32
  • 1
    Alternatively, trying loading the tileJSON with jQuery's $.ajax, which is more permissive w/ what can and can't be passed. Jan 14, 2015 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.