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.0.tar.gz (35.8 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.0-py3-none-any.whl (46.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: osmsg-1.1.0.tar.gz
  • Upload date:
  • Size: 35.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","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.0.tar.gz
Algorithm Hash digest
SHA256 65fdd7cdef253f69b821351066ed711cc82a291e63e9b55b2b1a3809b05943c2
MD5 461746dc2db000f5bc403dd30425b987
BLAKE2b-256 3dbf823be0255d1e6870c0c30044f0696712ca9285f9cf6c4a1adc86131bbac6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: osmsg-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6359db2337d5809b44f5e7fbfedfd7e44d9b8b2c3f4522fabb0d95d269f23ffa
MD5 348fc033a5442e42a8eba518616a8eae
BLAKE2b-256 84a78238203c3503bc005b31fa86f7e9f5ca1db8ece4b96fb5943513cc7a9ceb

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