How to Inspect PMTiles Metadata with CLI Tools

Use the pmtiles show CLI command to dump the complete JSON header from any PMTiles archive, exposing tile bounds, min/max zoom, tile format, compression algorithm, and the embedded metadata object. Pipe output to jq for CI/CD validation.

Installation & Prerequisites

The official PMTiles CLI (pmtiles) is a Go binary distributed from protomaps/go-pmtiles. Download the pre-built binary for your platform and place it on your PATH:

bash
# Linux (x86_64) — check releases page for the latest version
curl -L https://github.com/protomaps/go-pmtiles/releases/latest/download/go-pmtiles_Linux_x86_64.tar.gz \
  | tar xz pmtiles
sudo mv pmtiles /usr/local/bin/

# macOS (Homebrew)
brew install protomaps/homebrew-tools/go-pmtiles

Verify the installation:

bash
pmtiles --version

The CLI reads the v3 binary header directly from disk or from a remote URL via HTTP range requests, validating archives without loading the entire file into RAM.

Core CLI Commands & jq Extraction

Once installed, inspect any .pmtiles archive with a single command. The output is JSON, making it ideal for piping into downstream tools.

bash
# Dump full header + embedded metadata as formatted JSON
pmtiles show archive.pmtiles | jq .

# Extract only the embedded metadata object
pmtiles show archive.pmtiles | jq '.metadata'

# Validate tile coverage, zoom range, and format
pmtiles show archive.pmtiles | jq '{
  bounds: .bounds,
  center: .center,
  min_zoom: .minZoom,
  max_zoom: .maxZoom,
  tile_type: .tileType,
  compression: .tileCompression
}'

For developers unfamiliar with JSON query syntax, the official jq manual provides comprehensive examples for filtering nested structures.

Decoding Header Fields & Numeric Codes

The PMTiles v3 specification uses compact integer enums to minimize header size. Misinterpreting these values is the most common cause of broken tile requests in production.

Tile Type (tileType):

Numeric Code Meaning
0 Unknown / Other
1 MVT Vector Tile
2 PNG (Raster)
3 JPEG (Raster)
4 WebP (Raster)
5 AVIF (Raster)

Tile Compression (tileCompression) and Internal Compression (internalCompression):

Numeric Code Meaning
0 Unknown
1 None
2 gzip
3 Brotli
4 Zstandard (zstd)

For example, a vector tile archive with gzip compression will report tileType: 1 and tileCompression: 2. A tile server expecting zstd-compressed MVTs (tileCompression: 4) will fail to decode gzip tiles at runtime.

When designing Vector Tile Architecture & Format Fundamentals pipelines, verifying these fields early prevents mismatched decoder errors. Bounds are stored as [min_lon, min_lat, max_lon, max_lat] in WGS84 decimal degrees. Always cross-reference these values against your project’s geographic scope before deployment. For a complete breakdown of the binary layout and directory indexing, consult the PMTiles Specification Deep Dive.

Python Automation (Memory-Mapped Reader)

For Python automation, the pmtiles package provides a reader that avoids loading the full archive. Install it from PyPI:

bash
pip install pmtiles
python
from pmtiles.reader import Reader, MmapSource
import json
import sys

def inspect_pmtiles(filepath: str) -> dict:
    """Parse PMTiles v3 header and metadata without loading the full archive."""
    try:
        with open(filepath, "r+b") as f:
            source = MmapSource(f)
            reader = Reader(source)

            header = reader.header()
            metadata = json.loads(reader.metadata())

            # Coordinates are stored as E7 integers (value * 10_000_000)
            bounds = [
                header["min_lon_e7"] / 1e7,
                header["min_lat_e7"] / 1e7,
                header["max_lon_e7"] / 1e7,
                header["max_lat_e7"] / 1e7
            ]

            return {
                "spec_version":      header["spec_version"],
                "tile_type":         header["tile_type"],
                "tile_compression":  header["tile_compression"],
                "min_zoom":          header["min_zoom"],
                "max_zoom":          header["max_zoom"],
                "bounds":            bounds,
                "metadata_keys":     list(metadata.keys()),
                "vector_layers":     metadata.get("vector_layers", [])
            }
    except FileNotFoundError:
        print(f"Error: {filepath} not found.", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"Inspection failed: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    result = inspect_pmtiles("data.pmtiles")
    print(json.dumps(result, indent=2))

The script handles missing files and malformed archives, printing diagnostics to stderr and structured JSON to stdout. Note that reader.metadata() returns a raw JSON string; call json.loads() to access nested keys like vector_layers or attribution.

CI/CD Validation Patterns

Integrating PMTiles inspection into automated workflows catches packaging errors before they reach staging or production.

GitHub Actions / GitLab CI

yaml
- name: Validate PMTiles Archive
  run: |
    # Validate that the archive is an MVT (tileType=1) with gzip compression (tileCompression=2)
    pmtiles show dist/map.pmtiles | jq -e '.tileType == 1 and .tileCompression == 2'

The -e flag makes jq exit with a non-zero status if the condition is false, automatically failing the pipeline when tile type or compression does not match expectations.

Python-Based Validation Hook

python
import subprocess
import json
import sys

def validate_pmtiles_cli(path: str) -> bool:
    result = subprocess.run(
        ["pmtiles", "show", path],
        capture_output=True, text=True, check=True
    )
    header = json.loads(result.stdout)
    return (
        header["minZoom"] <= header["maxZoom"]
        and len(header["bounds"]) == 4
        and header["tileType"] == 1  # MVT
    )

When building automated tile generation workflows, always validate bounds alignment, zoom continuity, and tile type. Out-of-range tiles or missing directory entries will silently degrade map rendering or trigger excessive fallback requests. The official PMTiles repository maintains updated tooling and test fixtures to help standardize validation across teams.