Download a map picture with python


I would like to generate offline maps for some sets of pictures I have taken.
The pictures exif contain GPS data.

Now I would like to download a simple static map picture which covers a specified area.
e.g. what you see when open

I tried overpass but not sure how to get a map picture, looks complicated to me. looks good, but not sure how long term available this service is and requires a property tool.

What I want:

  • normal map, with default labeling
  • specified resolution of picture e.g. 800x600px
  • query to adjust the view, best would be a limit for n,s,w,e
  • long term availability to avoid maintaining my script

Is there a simple way to download such an image with python?

Thanks a lot for your help and ideas!

br Lukas

Maybe the API for my maposmatic instance could be of use for you?

I have been running that maposmatic instance for over 5 years now (although the API is a bit younger than that), and don’t have any plans to discontinue it any time soon. But you could also run your own instance, I also provide a Vagrant setup for this on github that you can throw a OSM data extract (or full planet, if you have the resources) in PBF format and it should start up a full working local instance form there:

Cool, sounds great.
But if I enter to my browser I get “Page not found”

import requests
import shutil
data = {'title': 'Python Test',
    'bbox_bottom':  '52.00',
    'bbox_top': '52.02', 
    'bbox_left' : '8.50',
    'bbox_right' :  '8.52'}
r ="", json={'json_payload': data}, stream=True)
with open('test', 'wb') as out_file:
    shutil.copyfileobj(r.raw, out_file)
del r

I’m not a coding expert, so maybe I do something completely wrong.

Thanks a lot!

Most basic Python example I can offer for now would be:

#! /usr/bin/python3

import json
import urllib3
from pprint import pprint
from time import sleep

base_url = ''

http = urllib3.PoolManager()

def api_call(url, data = None):
    if data is None:    
        r = http.request('GET', url)
        encoded_data = json.dumps(data).encode('utf-8')

        r = http.request(
            body = encoded_data,
            headers={'Content-Type': 'application/json'})
    return json.loads('utf-8'))

data = {
    "title": "API Test",
    "osmid": -4220331,

r = api_call(base_url + 'jobs/', data)

job_id = r['id']

job_status = 0

while job_status < 2:
    r = api_call(base_url + 'jobs/%d' % job_id)
    job_status = r['status']

r = http.request('GET',

with open('result.png', 'wb') as out:
    while True:
        data =
        if not data:


I just now used it to produce

Thank you for this code. It works great.

Still is there a way to speed the upload of the map ? On my machine it takes like 40-50s to load the map. I do not know if this is normal. High fidelity is not so important in my use case.


Hello Everyone,

Since a few weeks when running the same code as you presented, I get the following error

{'error': {'indexer': ['This field cannot be blank.']}}

I cannot find the reason for the issue. Could you please help me find out what’s happening ?

Thank you