Python Quickstart
Use server-side: tile proxying, batch geocoding, downloads, signed-URL signing.
For client-side maps in a Python web app (Streamlit, Dash, Flask templates), serve our style URL straight to MapLibre in the browser.
Install
bash
pip install requestsTile proxy (Flask)
python
import os
import time
import hmac
import hashlib
from flask import Flask, request, Response
import requests
app = Flask(__name__)
KEY = os.environ['MFD_SRV_KEY']
SECRET = os.environ['MFD_SRV_SECRET']
TILE_BASE = 'https://tiles.mapsfordevs.com'
def sign(method: str, path: str) -> dict:
ts = str(int(time.time()))
sig = hmac.new(SECRET.encode(), f'{method}\n{path}\n{ts}'.encode(), hashlib.sha256).hexdigest()
return {'Authorization': f'Bearer {KEY}', 'X-MFD-Timestamp': ts, 'X-MFD-Signature': sig}
@app.route('/tiles/<int:z>/<int:x>/<int:y>.pbf')
def tile(z, x, y):
path = f'/tiles/{z}/{x}/{y}.pbf'
upstream = requests.get(f'{TILE_BASE}{path}', headers=sign('GET', path), stream=True)
return Response(
upstream.iter_content(8192),
status=upstream.status_code,
content_type='application/x-protobuf',
headers={'Cache-Control': 'public, max-age=86400'}
)Batch geocoding
python
import requests
KEY = 'mfd_pub_xxx'
def geocode(query: str, country: str = None, limit: int = 5):
params = {'q': query, 'limit': limit}
if country:
params['country'] = country
r = requests.get(
'https://api.mapsfordevs.com/geocode/forward',
headers={'Authorization': f'Bearer {KEY}'},
params=params,
timeout=10
)
body = r.json()
if not body.get('ok'):
raise RuntimeError(body.get('error'))
return body['items']
results = geocode('80 Sturdee Ave Rosebank', country='za')
for hit in results:
print(hit['lat'], hit['lng'], hit['label'])Download a country .mfdmap
python
import requests
PUB_KEY = 'mfd_pub_xxx'
def buy_country(slug: str, plan: str = 'perpetual'):
r = requests.post(
'https://api.mapsfordevs.com/downloads/purchase',
headers={'Authorization': f'Bearer {PUB_KEY}'},
json={'countrySlug': slug, 'plan': plan},
timeout=30
)
r.raise_for_status()
return r.json()['licenseToken']
def fetch_mfdmap(token: str, dest_path: str):
r = requests.get(f'https://api.mapsfordevs.com/downloads/{token}', timeout=30)
url = r.json()['url']
with requests.get(url, stream=True, timeout=600) as resp:
resp.raise_for_status()
with open(dest_path, 'wb') as f:
for chunk in resp.iter_content(1024 * 1024):
f.write(chunk)
token = buy_country('south-africa', 'perpetual')
fetch_mfdmap(token, '/data/za.mfdmap')Retry with backoff
python
import time
import requests
from requests.exceptions import RequestException
def fetch_with_retry(url, headers=None, attempts=4):
for i in range(attempts):
try:
r = requests.get(url, headers=headers, timeout=10)
if r.status_code < 500 and r.status_code != 429:
return r
delay = int(r.headers.get('Retry-After', 0)) or (2 ** i)
except RequestException:
delay = 2 ** i
time.sleep(delay)
raise RuntimeError(f'failed after {attempts} attempts')