Sofar API
Tile Server
This endpoint returns raster tiles (images) of our time series weather data. The tile endpoint can be used with a mapping client, such as Leaflet.js or Mapbox, to make an interactive world map.
Get Tile PNG

Example Usage

The following HTML code uses Mapbox GL JS to display model data served by our Tile Server API. The page features a slider that allows you to select the desired time (anywhere from 24 hours in the past, to 6 hours in the future). You can run this demo either by visiting the file in a local browser or using the code pen featured below.
<!-- Simple example using mapbox-gl-js along with the Sofar tile api to create a map that shows data from a certain model/variable at various times-->
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Sofar Tile Server Demo</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src=""></script>
<script src=""></script>
<script src=""></script>
<link href="" rel="stylesheet" />
body { margin: 0; padding: 0; font-family: sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#model-info {
position: relative;
background-color: #eee;
margin: 5px;
padding: 5px;
display: inline-block;
#map-overlay {
position: relative;
margin: 5px;
padding: 5px;
display: inline-block;
<div id="map"></div>
<div id="model-info">
<b>Model:</b> <label id="model-name"></label> <br>
<b>Variable:</b> <label id="variable-name"></label> <br>
<div id="map-overlay">
<b>Inference Time:</b>
<label id="timestamp"></label>
<input id="slider" type="range" min="0" max="4" step="1" value="3" />
// link used to access the sofar api. The timestamp is appended on dynamically as the slider changes
// This particular demo accesses significant wave height data from the Sofar Wave Model
const modelName = "SofarOperationalWaveModel"
const variableName = "significantWaveHeight";
const cmap = "turbo";
const sofarApiToken = "383d59964809ca8c6438867e590f16";
// get closest available hour
const modelTimesEndpoint =
"" +
modelName +
"/outputTimes?token=" +
sofarApiToken +
"&closest=" +
const linkPrefix =
"" +
modelName +
+ cmap +
"&token=" +
sofarApiToken +
"&variableID=" +
variableName +
$.get( modelTimesEndpoint, function( data ) {
// upon loading a valid model time, use that as a starting point
const timestamp = moment(data.outputTimes[0]);
// Add 30 hours of available times to the slider. 1 day ago to 6 hours in the future
const dates = [];
const startDate = timestamp.subtract(1, "day");
for (let i = 0; i < 5; i++) {
dates.push(startDate.add(6, "hour").toISOString());
// update info box
document.getElementById("model-name").textContent = modelName;
document.getElementById("variable-name").textContent = variableName;
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9uc2VuIiwiYSI6IkR6UU9oMDQifQ.dymRIgqv-UV6oz0-HCFx1w'
let map = new mapboxgl.Map({
container: "map", // container id
style: "mapbox://styles/jonsen/ck8i301kh0cy31ipfi7y8j6bb",
center: [-74.5, 40], // starting position
zoom: 2, // starting zoom
// Function that updates the map data based on the current slider timestamp
function updateDate(newIndex) {
let currentTime = dates[newIndex];
document.getElementById("timestamp").textContent = currentTime;
let link = linkPrefix + currentTime;
map.addSource("sofar-tiles", {
type: "raster",
tiles: [link],
tileSize: 256,
attribution: "Sofar Ocean Technologies"
id: "sofar-tiles",
type: "raster",
source: "sofar-tiles",
minzoom: 0,
maxzoon: 10
map.on("load", function () {
// set to be the current time which has index 23
document.getElementById("slider").addEventListener("input", function (e) {
const dateIndex = parseInt(, 10);
if (map.getLayer("sofar-tiles")) map.removeLayer("sofar-tiles");
if (map.getSource("sofar-tiles")) map.removeSource("sofar-tiles");

Additional Information

Colormap Options