Skip to content

Cloud Storage Platforms for PMTiles


PMTiles is designed to work on any S3-compatible cloud storage platform that supports HTTP Range Requests. Proper support for Cross-Origin Resource Sharing is required if your map frontend is hosted on a different domain than your storage platform.


  • Most cloud storage platforms support moderate-size uploads through a web interface.

  • The pmtiles command line tool has a pmtiles upload command for moving files to cloud storage. This requires credentials with your specific platform.

  • RClone is another recommended tool for managing large files on S3-compatible storage.

  • The aws command-line tool can be used for uploads, as well as setting CORS configuration on any S3-compatible platform.


Storage services usually bill by number of GET requests and the total number of bytes stored. It's important to understand these costs when hosting PMTiles, as each Range tile request will count as a GET.

Recommended Platforms

Cloudflare R2

R2 is the recommended storage platform for PMTiles because it does not have bandwidth fees.

  • R2 supports HTTP/2.

  • R2 CORS must be configured through a command-line utility like the aws tool:

aws s3api put-bucket-cors --bucket MY_BUCKET --cors-configuration file:///home/user/cors_rules.json

Amazon S3

  • only HTTP/1.1 supported

  • From your S3 Bucket's "Permissions" tab, scroll to the Cross-origin resource sharing (CORS) editor.

S3 Policy for public reads:

    "Version": "2012-10-17",
    "Id": "",
    "Statement": [
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::example-bucket/*"

S3 CORS Configuration:

        "AllowedHeaders": ["Range"],
        "AllowedMethods": ["GET","HEAD"],
        "AllowedOrigins": [""],
        "ExposeHeaders": ["ETag"]
  1. Ensure that your PMTiles has public read access:

Google Cloud

      "origin": [""],
      "method": ["GET","HEAD"],
      "responseHeader": ["range","etag"],
      "maxAgeSeconds": 300
gsutil cors set google_cloud_cors.json gs://my-bucket-name

Microsoft Azure

  • only HTTP/1.1 supported

  • Configuration through Web Portal

  • CORS Configuration - in left sidebar Resource Sharing (CORS)

    • Set Allowed Headers to Range
    • Set Exposed Headers to range,accept-ranges,etag

DigitalOcean Spaces

  • only HTTP/1.1 supported (even with CDN enabled)

  • CORS is configured via Web UI.

  • use S3Cmd config to expose ETag header

Backblaze B2

Sample CORS Configuration:

      "corsRuleName": "allowHeaders",
      "allowedOrigins": [""],
      "allowedHeaders": ["range"],
      "maxAgeSeconds": 300

Other Platforms

GitHub Pages

GitHub pages supports repositories up to 1 GB. If your PMTiles file fits, it's an easy way to host.


Scaleway Object Storage only supports HTTP/1.1.

HTTP Servers

  • Nginx supports HTTP Range Requests. CORS headers should be set by configuration files.

  • Caddy has known issues with serving large (> 5 GB) archives to particular browsers and is not officially supported right now.

Next steps