Where did my GCP money go? gcp-costtree reads your Cloud Billing BigQuery export and writes one
self-contained HTML treemap: box size is cost, you drill down from service to SKU to resource, waste
is hatched, and you can mark boxes to build a savings list.
Inspired by awstree and disktree; see Credits.
python3 gcp_costtree.py --demo # fake data, no GCP access
python3 gcp_costtree.py --table PROJECT.DATASET.TABLE --dry-run
python3 gcp_costtree.py --table PROJECT.DATASET.TABLE --label env
Needs Python 3.11+ and the gcloud CLI (or a token in GCP_COSTTREE_TOKEN). No pip installs.
- Enable the billing export: Billing → your account → Billing export → BigQuery export. Enable
Detailed usage cost for resource-level boxes, or Standard usage cost for the cheaper
service/SKU view. Use a
USorEUmulti-region dataset. The first data can take hours to arrive. - Permissions:
bigquery.jobs.createon the project that runs the queries (--job-project, default: the table's project), andbigquery.tables.get+bigquery.tables.getDataon the export table. - For a service account:
export GCP_COSTTREE_TOKEN="$(gcloud auth print-access-token --impersonate-service-account=SA_EMAIL)".
Each run does a free dry run first and stops if a query would scan more than --max-gb (default 50 GB
per query). A 30-day run on a mid-size detailed export scans about 0.1–1 GB. --from out/gcp-costtree-data.json
re-renders without querying.
out/gcp-costtree.html: the viewer. Works offline; it makes no network requests.out/gcp-costtree-data.json: the cache, written next to the HTML (so--outmoves it too).--export: a compact JSON summary (≤ 64 KB) for AI agents. Pressein the viewer for the same summary plus your marks (the viewer's copy is trimmed to 48 KB first to leave room for them).
The HTML contains project IDs, resource names, and label values. Share it accordingly. The billing account ID is left out.
- Usage period, not invoice. Costs are attributed to the UTC day the usage started. Totals won't match an invoice, and the Billing console (Pacific time) can differ at day edges. Monthly charges (support fees, some subscriptions) start on the 1st of the month, so a window that starts later leaves them out.
- net = cost + credits (what you pay); cost = before credits; list = list price.
- The last
--lag-daysdays (default 2) are skipped because the export arrives late; the last included day is marked provisional. Re-running later can change totals. --end YYYY-MM-DDpicks the last day of the period instead, for example while a new export is still backfilling:--end 2026-08-25 --days 14. It must be before today (UTC),--lag-daysis then ignored, and in the config file it isend = "2026-08-25". The last day is still marked provisional (late rows can revise any day). The scan covers partitions up to today, so an old window can need a higher--max-gb.- Comparisons use the previous period of the same length. If the export doesn't reach back that far, comparisons and the growth rule are switched off.
- The resource level (detailed export) keeps the top N resources per SKU (
--top-resources) across all projects; the rest is(other). In the project view, a small project's SKU can show only(other).
? in the viewer lists them all. Arrows move, Enter opens, Backspace goes up, 1–9 regroup,
m switches metric, c colors by change, x marks, r reviews marks, / filters by any name (service, SKU, project, region, label value, resource), e exports.
See examples/gcp-costtree.example.toml. CLI flags override the config file. Rules can be disabled,
re-thresholded (amounts are in the export's currency), or added.
python3 -m unittest discover -s tests -t .
node --test tests/viewer.test.mjs # optional, Node 20+
- disktree by Tobi Lütke: inspiration for the drill-down treemap, keyboard navigation, category colors, hatching for reclaimable items, and marking boxes for review.
- awstree by Branko Petric: the same idea applied to a cloud bill, and the viewer's layout and CSS, which gcp-costtree adapts (MIT; see License).
- Colors are based on Google's brand and Material palettes. gcp-costtree is not affiliated with or endorsed by Google.
MIT, Copyright (c) 2026 Alexios Polyzos. See LICENSE.
viewer.html includes layout and CSS adapted from awstree, Copyright (c) 2026 Branko Petric, under the MIT License;
that notice is reproduced at the top of viewer.html.
