OpenStreetMap Stats Generator: Commandline
Project description
osmsg
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
- Installation
- Manual (every flag, with examples)
- Self-hosting / Docker Compose
- Version control / release notes
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2d31b597a12f4dd097f14670c8634e36be8b6e21bfb9e8ef646332152c39d37
|
|
| MD5 |
67b504105a2597a4f32f9e755ee376d6
|
|
| BLAKE2b-256 |
670cb6abbd7db55065078682ecbd6ce9e3114ef1af02cd72ed6aca7429e6505c
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12daeec0791e92eb958579467262a356b70a669152d60dc1fcd469ad1a448f89
|
|
| MD5 |
e2e148b8624de2b7d11135461fdb0d4f
|
|
| BLAKE2b-256 |
6e6582fdb5667dd423ad37ade8766844dcc029449e67af1d1509b624134f522e
|