diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c55829b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+build
+dist
+
+env
+env3
+
+*.vrt
+*.egg-info
+*.pyc
+
+*.yml
diff --git a/README.md b/README.md
index 6d56be4..6b81071 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,43 @@
-# wms-downloader
-Downloads large geo TIFF files from a WMS service.
+wms-downloader
+==============
+
+Install
+-------
+
+```bash
+    pip install wms-downloader
+```
+
+Usage
+-----
+
+Create a `config.yml` specifying your setup like this:
+
+```yml
+service:
+  version: 1.1.1
+  url: http://fbinter.stadt-berlin.de/fb/wms/senstadt/k_luftbild1953?
+  srs: EPSG:25833
+  format: jpeg
+  layer: 0
+bbox:
+  west:   370000.0
+  south: 5800000.0
+  east:   415000.0
+  north: 5837000.0
+
+size: 10000
+resolution: 600
+timeout: 300
+projection: EPSG:25833
+directory: images
+vrtfile: tiles.vrt
+tmpfile: /tmp/wms.xml
+```
+
+Then run the script in the same directory as `config.yml` or use the `-c` argument:
+
+```
+    wms-downloader
+    wms-downloader -c /path/to/my_custom_config.yml
+```
diff --git a/bin/wms-downloader b/bin/wms-downloader
new file mode 100644
index 0000000..d3ed1f4
--- /dev/null
+++ b/bin/wms-downloader
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+
+from  wms_downloader.download import main
+main()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..1a7eb43
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+
+from wms_downloader import (
+    __title__ as title,
+    __version__ as version,
+    __author__ as author,
+    __license__ as license
+)
+
+description = 'Downloads large geo TIFF files from a WMS service.'
+email = 'jochenklar@gmail.com'
+url = 'https://github.com/jochenklar/wms-downloader'
+
+requirements = [
+    'mercantile',
+    'PyYAML',
+    'numpy'
+]
+
+scripts = [
+    'bin/wms-downloader'
+]
+
+setup(
+    name=title,
+    version=version,
+    description=description,
+    url=url,
+    author=author,
+    author_email=email,
+    maintainer=author,
+    maintainer_email=email,
+    license=license,
+    packages=find_packages(),
+    install_requires=requirements,
+    classifiers=[],
+    scripts=scripts,
+)
diff --git a/wms_downloader/__init__.py b/wms_downloader/__init__.py
new file mode 100644
index 0000000..686dcb0
--- /dev/null
+++ b/wms_downloader/__init__.py
@@ -0,0 +1,5 @@
+__title__ = 'wms-downloader'
+__version__ = '1.0.0'
+__author__ = 'Jochen Klar'
+__license__ = 'MIT'
+__copyright__ = 'Copyright 2017 Jochen Klar'
diff --git a/wms_downloader/download.py b/wms_downloader/download.py
new file mode 100755
index 0000000..f15bb87
--- /dev/null
+++ b/wms_downloader/download.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+import argparse
+import os
+import subprocess
+import yaml
+
+
+xml_template = '''<GDAL_WMS>
+  <Service name="WMS">
+    <Version>%(version)s</Version>
+    <ServerUrl>%(url)s</ServerUrl>
+    <SRS>%(srs)s</SRS>
+    <ImageFormat>image/%(format)s</ImageFormat>
+    <Layers>%(layer)s</Layers>
+  </Service>
+  <DataWindow>
+    <UpperLeftX>%(west)s</UpperLeftX>
+    <UpperLeftY>%(north)s</UpperLeftY>
+    <LowerRightX>%(east)s</LowerRightX>
+    <LowerRightY>%(south)s</LowerRightY>
+    <SizeX>%(resolution)s</SizeX>
+    <SizeY>%(resolution)s</SizeY>
+  </DataWindow>
+  <Timeout>%(timeout)s</Timeout>
+  <Projection>%(projection)s</Projection>
+</GDAL_WMS>'''
+
+
+def main():
+    parser = argparse.ArgumentParser(usage='Downloads large geo TIFF files from a WMS service.')
+    parser.add_argument('config', nargs='?', default='config.yml', help='config file [default: config.yml]')
+    args = parser.parse_args()
+
+    with open(args.config) as f:
+        config = yaml.load(f.read())
+
+    try:
+        os.makedirs(config['directory'])
+    except OSError:
+        pass
+
+    west_range = list(arange(config['bbox']['west'], config['bbox']['east'], config['size']))
+    south_range = list(arange(config['bbox']['south'], config['bbox']['north'], config['size']))
+
+    for west in west_range:
+        for south in south_range:
+            filename = '%(directory)s/%(west)s_%(south)s_%(resolution)s.gdal.tif' % {
+                'directory': config['directory'],
+                'west': west,
+                'south': south,
+                'resolution': config['resolution']
+            }
+
+            if not os.path.exists(filename + '.aux.xml'):
+                print(filename)
+
+                xml_params = {
+                    'west': west,
+                    'south': south,
+                    'east': west + config['size'],
+                    'north': south + config['size'],
+                    'resolution': config['resolution'],
+                    'timeout': config['timeout'],
+                    'projection': config['projection']
+                }
+                xml_params.update(config['service'])
+
+                with open(config['tmpfile'], 'w') as f:
+                    f.write(xml_template % xml_params)
+
+                args = ['gdal_translate', '-of', 'JPEG', config['tmpfile'], filename]
+                subprocess.check_call(args)
+
+    file_pattern = '%s/*.gdal.tif'
+    args = ['gdalbuildvrt', '-a_srs', config['projection'], '-overwrite', config['vrtfile'], file_pattern]
+    subprocess.check_call(args)
+
+
+def arange(start, stop, step):
+    current = start
+    while current < stop:
+        yield current
+        current += step
+
+if __name__ == "__main__":
+    main()