Skip to content
Cloud Optimized GeoTIFF creation and validation plugin for rasterio
Branch: master
Clone or download
Latest commit 0f0f801 Apr 19, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci fix ci regex Feb 12, 2019
rio_cogeo release 1.0.0 Apr 19, 2019
tests update from master Apr 17, 2019
.gitignore add cogeo tests Mar 27, 2018
.pre-commit-config.yaml blackify + pre-commit + documentation Jun 13, 2018
CHANGES.txt release 1.0.0 Apr 19, 2019
LICENSE Initial commit Mar 9, 2018
README.rst update docs [skip ci] Apr 19, 2019
codecov.yml add ci Apr 18, 2018
requirements.txt Update requirements and fix documentations (#39) Nov 15, 2018 update from master Apr 17, 2019
tox.ini merge from master and fix max_zoom calculation Apr 1, 2019



Cloud Optimized GeoTIFF (COG) creation and validation plugin for Rasterio

Cloud Optimized GeoTIFF

This plugin aim to facilitate the creation and validation of Cloud Optimized GeoTIFF (COG or COGEO). While it respects the COG specifications, this plugin also enforce several features:

  • Internal overviews (User can remove overview with option --overview-level 0)
  • Internal tiles (default profiles have 512x512 internal tiles)


$ pip install -U pip
$ pip install rio-cogeo

Or install from source:

$ git clone
$ cd rio-cogeo
$ pip install -U pip
$ pip install -e .


$ rio cogeo --help
  Usage: rio cogeo [OPTIONS] COMMAND [ARGS]...

  Rasterio cogeo subcommands.

    --help  Show this message and exit.

    create    Create COGEO
    validate  Validate COGEO
  • Create a Cloud Optimized Geotiff.
$ rio cogeo create --help
  Usage: rio cogeo create [OPTIONS] INPUT OUTPUT

  Create Cloud Optimized Geotiff.

    -b, --bidx BIDX                 Band indexes to copy.
    -p, --cog-profile [jpeg|webp|zstd|lzw|deflate|packbits|raw] CloudOptimized GeoTIFF profile (default: deflate).
    --nodata NUMBER|nan             Set nodata masking values for input dataset.
    --add-mask                      Force output dataset creation with an internal mask (convert alpha band or nodata to mask).
    --overview-level INTEGER        Overview level (if not provided, appropriate overview level will be selected
                                    until the smallest overview is smaller than the value of the internal blocksize)
    --overview-resampling [nearest|bilinear|cubic|cubic_spline|lanczos|average|mode|gauss] Overview creation resampling algorithm.
    --overview-blocksize TEXT       Overview's internal tile size (default defined by GDAL_TIFF_OVR_BLOCKSIZE env or 128)
    -w, --web-optimized             Create COGEO optimized for Web.
    --latitude-adjustment / --global-maxzoom
                                    Use dataset native mercator resolution for MAX_ZOOM calculation (linked to dataset center latitude, default)
                                    or ensure MAX_ZOOM equality for multiple dataset accross latitudes.
    -r, --resampling [nearest|bilinear|cubic|cubic_spline|lanczos|average|mode|gauss] Resampling algorithm.
    --in-memory / --no-in-memory    Force processing raster in memory / not in memory (default: process in memory if smaller than 120 million pixels)
    --threads INTEGER
    --co, --profile NAME=VALUE      Driver specific creation options.See the documentation for the selected output driver for more information.
    -q, --quiet                     Remove progressbar and other non-error output.
    --help                          Show this message and exit.
  • Check if a Cloud Optimized Geotiff is valid.
$ rio cogeo validate --help
  Usage: rio cogeo validate [OPTIONS] INPUT

  Validate Cloud Optimized Geotiff.

    --help  Show this message and exit.


# Create a COGEO with DEFLATE compression (Using default `Deflate` profile)
$ rio cogeo create mydataset.tif mydataset_jpeg.tif

# Validate COGEO
$ rio cogeo validate mydataset_jpeg.tif

# Create a COGEO with JPEG profile and the first 3 bands of the data and add internal mask
$ rio cogeo create mydataset.tif mydataset_jpeg.tif -b 1,2,3 --add-mask --cog-profile jpeg

Default COGEO profiles


  • JPEG compression
  • PIXEL interleave
  • YCbCr colorspace
  • limited to uint8 datatype and 3 bands data


  • WEBP compression
  • PIXEL interleave
  • limited to uint8 datatype and 3 or 4 bands data
  • Available for GDAL>=2.4.0


  • ZSTD compression
  • PIXEL interleave
  • Available for GDAL>=2.3.0

Note in Nov 2018, there was a change in libtiff's ZSTD tags which create incompatibility for old ZSTD compressed GeoTIFF link


  • LZW compression
  • PIXEL interleave


  • DEFLATE compression
  • PIXEL interleave


  • PACKBITS compression
  • PIXEL interleave


  • NO compression
  • PIXEL interleave

Default profiles are tiled with 512x512 blocksizes.

Profiles can be extended by providing '--co' option in command line

# Create a COGEO without compression and with 1024x1024 block size and 256 overview blocksize
$ rio cogeo create mydataset.tif mydataset_raw.tif --co BLOCKXSIZE=1024 --co BLOCKYSIZE=1024 --cog-profile raw --overview-blocksize 256

Web-Optimized COG

rio-cogeo provide a --web-optimized option which aims to create a web-tiling friendly COG.

Output dataset features:

  • bounds and internal tiles aligned with web-mercator grid.
  • raw data and overviews resolution match mercator zoom level resolution.


Because the mercator project does not respect the distance, when working with multiple images covering different latitudes, you may want to use the --global-maxzoom option to create output dataset having the same MAX_ZOOM (raw data resolution).

Because it will certainly create a larger file, a nodata value or alpha band should be present in the input dataset. If not the original data will be surrounded by black (0) data.

Internal tile size

By default rio cogeo will create a dataset with 512x512 internal tile size. This can be updated by passing --co BLOCKXSIZE=64 --co BLOCKYSIZE=64 options.

Web tiling optimization

if the input dataset is aligned to web mercator grid, the internal tile size should be equal to the web map tile size (256 or 512px). Dataset should be compressed.

if the input dataset is not aligned to web mercator grid, the tiler will need to fetch multiple internal tiles. Because GDAL can merge range request, using small internal tiles (e.g 128) will reduce the number of byte transfered and minimized the useless bytes transfered.

GDAL configuration to merge consecutive range requests


Overview levels

By default rio cogeo will calculate the optimal overview level based on dataset size and internal tile size (overview should not be smaller than internal tile size (e.g 512px). Overview level will be translated to decimation level of power of two:

overview_level = 3
overviews = [2 ** j for j in range(1, overview_level + 1)]
[2, 4, 8]

GDAL Version

It is recommanded to use GDAL > 2.3.2. Previous version might not be able to create proper COGs (ref:

More info in

Nodata, Alpha and Mask

By default rio-cogeo will forward any nodata value or alpha channel to the output COG.

If your dataset type is Byte or Unit16, you could use internal bit mask (with the --add-mask option) to replace the Nodata value or Alpha band in output dataset (supported by most GDAL based backends).

Note: when adding a mask with an input dataset having an alpha band you'll need to use the bidx options to remove it from the output dataset.

# Replace the alpha band by an internal mask
$ rio cogeo mydataset_withalpha.tif mydataset_withmask.tif --cog-profile raw --add-mask --bidx 1,2,3


Using internal nodata value with lossy compression (webp, jpeg) is not recommanded. Please use internal masking (or alpha band if using webp).


Some libraries might request to use COGs with statistics written in the internal metadata. rio-cogeo doesn't calculate nor copy those when creating the output dataset (because statistics may change due to lossy compression). To add the statistics to the output dataset you could use the code above:

import rasterio

with"my-data.tif", "r+") as src_dst:
    for b in src_dst.indexes:
        band =, masked=masked)
        stats = {
            'min': float(band.min()),
            'max': float(band.max()),
            'mean': float(band.mean())
            'stddev': float(band.std())
        src_dst.update_tags(b, **stats)

Contribution & Development

The rio-cogeo project was begun at Mapbox and has been transferred to the CogeoTIFF organization in January 2019.

Issues and pull requests are more than welcome.

dev install

$ git clone
$ cd rio-cogeo
$ pip install -e .[dev]

Python3.6 only

This repo is set to use pre-commit to run flake8, pydocstring and black ("uncompromising Python code formatter") when commiting new code.

$ pre-commit install


Blog post on good and bad COG formats:

Checkout rio-glui rasterio plugin to explore COG locally in your web browser.

You can’t perform that action at this time.