Skip to main content

OpenStreetMap Stats Generator: Commandline

Project description

osmsg

CI Docker PyPI Python License: MIT Ruff uv Container

OpenStreetMap Stats Generator. A tiny CLI (and Python library) that turns OSM history into per-user counts of nodes, ways, and relations created, modified, or deleted, written to parquet, csv, json, markdown, or Postgres.

A Project of OSGeo Nepal.

Features

  • Per-user create/modify/delete counts over any time window.
  • Tag and hashtag breakdowns (e.g. building, #hotosm).
  • Country and custom-boundary filters via Geofabrik.
  • Cron-friendly resume with --update.
  • Outputs you can query: parquet, csv, json, markdown, DuckDB, Postgres.

Install

Pick the one that fits how you work.

uvx --from osmsg osmsg --last hour       # zero-install, one-shot run
pip install osmsg                        # into your project
uv tool install osmsg                    # standalone CLI
docker run --rm -v "$PWD:/work" -w /work ghcr.io/osgeonepal/osmsg:latest --last hour

uvx can run osmsg in a throwaway environment , no install, no virtualenv to manage. Works with any flag combination, e.g. uvx --from osmsg osmsg --last hour --tags building --summary -f parquet -f markdown.

Quick start

osmsg --last hour                        # planet, last hour
osmsg --last day --tags building         # last day with a tag breakdown
osmsg --hashtags hotosm --last day       # only changesets tagged #hotosm

That's it. A stats.duckdb and a stats.parquet show up in your current folder.

Tutorials

1. Stats for a country

osmsg --country nepal --last day

--country resolves through Geofabrik and needs an OSM account. Set OSM_USERNAME and OSM_PASSWORD in your shell or a .env file:

export OSM_USERNAME=you
export OSM_PASSWORD=secret

2. A custom date range with summaries

osmsg --start "2026-04-01" --end "2026-04-08" \
      --tags building --tags highway --summary

--summary adds a daily rollup file alongside the per-changeset stats.

3. Run on a schedule

osmsg --country nepal --update           # picks up where the last run stopped

Drop that into cron or a GitHub Actions schedule. State is stored inside the DuckDB file, so reruns are safe.

4. Query the output

duckdb stats.duckdb -c "SELECT username, SUM(nodes_created) AS n
                        FROM users JOIN changeset_stats USING (uid)
                        GROUP BY username ORDER BY n DESC LIMIT 10"

Same schema in DuckDB and Postgres: users, changesets, changeset_stats, state.

5. Run the API

Push stats into Postgres, then start the Litestar API:

osmsg --last day --format psql --psql-dsn "postgresql://user:pass@localhost/osmsg"
litestar --app api.app:app run --host 0.0.0.0 --port 8000
GET /health
GET /api/v1/user-stats?start=2026-05-01T00:00:00Z&end=2026-05-02T00:00:00Z
GET /docs

For self-hosting with Docker Compose and systemd, see docs/infra.md.

6. Use it as a library

from datetime import datetime, UTC
from osmsg import RunConfig, run

result = run(RunConfig(
    name="nepal",
    countries=["nepal"],
    start_date=datetime(2026, 4, 25, tzinfo=UTC),
    end_date=datetime(2026, 4, 26, tzinfo=UTC),
))
print(result["files"]["parquet"])

Same pipeline as the CLI.

7. Long flag lists? Use a config

osmsg --config nepal.yaml

Any flag works as a YAML key. See docs/Manual.md for the full list.

Output formats

Every run writes stats.duckdb (or <--name>.duckdb) plus the formats you ask for via -f parquet|csv|json|markdown|psql. Parquet is the default. Open it with duckdb, polars, pandas, anything.

Configuration

Every meaningful flag has a matching OSMSG_* env var so the CLI, a .env file, and a docker-compose environment: block all reach the same setting. CLI flag wins over env var.

CLI flag Env var Default Notes
--name OSMSG_NAME stats Output basename; sets <name>.duckdb.
--country OSMSG_COUNTRY unset Geofabrik region id(s). Comma-separated when set via env.
--boundary OSMSG_BOUNDARY unset GeoJSON path or inline GeoJSON.
--url OSMSG_URL minute minute/hour/day shortcut or full URL. Comma-separated when set via env.
--workers OSMSG_WORKERS cpu count Parallel workers.
--cache-dir OSMSG_CACHE_DIR platform cache Where downloaded OSM files are kept across runs.
--output-dir OSMSG_OUTPUT_DIR . Where <name>.duckdb and exports are written.
--format / -f OSMSG_FORMAT parquet Repeat for multiple. Comma-separated when set via env.
--psql-dsn OSMSG_PSQL_DSN unset libpq DSN for -f psql.
--changeset-pad-hours OSMSG_CHANGESET_PAD_HOURS 1 See below.
(auto-bootstrap on --update) OSMSG_BOOTSTRAP hour hour, day, or week. Used when --update runs against an empty DB.
(auto-bootstrap on --update) OSMSG_BOOTSTRAP_DAYS unset Integer N; overrides OSMSG_BOOTSTRAP.
OSM credentials (Geofabrik) OSM_USERNAME, OSM_PASSWORD unset Required only when a Geofabrik URL is in use.

A .env file at the working directory is loaded automatically.

Documentation

Contributing

Pull requests are welcome. Quick path:

git clone https://github.com/osgeonepal/osmsg && cd osmsg
git switch develop
uv sync
uv run pre-commit install
uv run pytest -m "not network"

Please read CONTRIBUTING.md and the Code of Conduct before opening a PR. Use Conventional Commits (cz commit).

License

MIT © OSGeo Nepal contributors.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

osmsg-1.1.1.tar.gz (35.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

osmsg-1.1.1-py3-none-any.whl (46.3 kB view details)

Uploaded Python 3

File details

Details for the file osmsg-1.1.1.tar.gz.

File metadata

  • Download URL: osmsg-1.1.1.tar.gz
  • Upload date:
  • Size: 35.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for osmsg-1.1.1.tar.gz
Algorithm Hash digest
SHA256 b2d31b597a12f4dd097f14670c8634e36be8b6e21bfb9e8ef646332152c39d37
MD5 67b504105a2597a4f32f9e755ee376d6
BLAKE2b-256 670cb6abbd7db55065078682ecbd6ce9e3114ef1af02cd72ed6aca7429e6505c

See more details on using hashes here.

File details

Details for the file osmsg-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: osmsg-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for osmsg-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 12daeec0791e92eb958579467262a356b70a669152d60dc1fcd469ad1a448f89
MD5 e2e148b8624de2b7d11135461fdb0d4f
BLAKE2b-256 6e6582fdb5667dd423ad37ade8766844dcc029449e67af1d1509b624134f522e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page