Grafana Dashboard Extractor
Pricing
from $0.35 / 1,000 records
Grafana Dashboard Extractor
Point at any Grafana instance and extract its dashboard + folder inventory, version and health via the open HTTP API. One row per dashboard/folder with title, uid, tags, folder; plus health and discovery modes. No per-host scraper.
Pricing
from $0.35 / 1,000 records
Rating
0.0
(0)
Developer
Datamule
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
a month ago
Last modified
Categories
Share
A GENERIC "point at any Grafana instance" Apify actor — the dashboard-inventory sibling of the netdata / gatus / uptime-kuma observability runners, over a different, far larger platform population. Grafana (grafana/grafana, ~66k★) is THE self-hosted dashboarding / observability platform, on virtually every observability stack, and a large fraction of instances leaves the HTTP API anonymous-readable — so ONE actor spans every instance, no per-host scraper and no host enumeration.
Input
| Field | Mode | Meaning |
|---|---|---|
sources (required) | all | One or more Grafana base URLs — https://play.grafana.org, https://grafana.wikimedia.org, or any self-hosted instance. The /api/... path is appended for you. |
mode | — | search (default), health, or discovery. |
query | search | Case-insensitive substring matched against dashboard/folder titles. |
type | search | dash-db (dashboards) or dash-folder (folders). Empty = both. |
tag | search | One or more tags (AND-ed by Grafana). |
maxRecords | all | Global cap across every source (one row = one billable event). |
bearer | all | Optional API key / service-account token (Authorization: Bearer). Never logged. |
extraHeaders | all | Optional extra request headers (JSON). |
Modes
- search (default) — paginated
/api/search→ one flat row per dashboard/folder:id,uid,title,kind(dashboard/folder/other),type,url,tags,isStarred,folderId/folderUid/folderTitle, plus the instance_version/_grafanaBuildCommit(best-effort from a cheap health probe) and a lossless_raw. - health —
/api/health(+ best-effort/api/frontend/settings) → one row per instance:database,version,commit,edition, and the non-secret auth fingerprint (disableLoginForm,samlEnabled,ldapEnabled,oauthProviders[names only],featureToggleCount). - discovery — health + settings + a bounded search count → one summary row per
instance:
version,edition,dashboardCount, andauthDisabled(did anonymous/api/searchreturn 200?). A cheap way to fingerprint many instances at once.
Behaviour
- Every field is read by key presence (
dict.get) — Grafana's/api/search+/api/healthshapes drift across the 8→13 major versions and instances populate different optional fields, so an entry omittingfolderTitle/tags/sortMetayieldsnull/[]for that column, never a crash. Unknown fields survive in_raw. - Many instances gate
/api/search(401/403) but leave/api/healthopen. In search mode, such a source falls back to a discovery row (the instance fingerprint) instead of yielding nothing. - A source behind an anti-bot interstitial (a non-JSON HTTP 200), unreachable (Cloudflare 52x), or returning a non-Grafana body is a clean skip-with-warning — the runner continues with the other sources. The run only fails fast (exit 91) when every source was skipped, so nothing broken ships and the cloud smoke gate stays honest.
- A valid instance with 0 matching dashboards → 0 records and a clean exit 0. Unpopular is fine; the actor never fabricates rows.
Pricing
Pay-per-event: one record charge per emitted dataset row.
Each row is charged as it is saved, within the maximum cost you set for the run. The Actor stops before it requests a search page or an instance your budget cannot pay for, so you never receive rows you did not pay for. If an instance fails after some rows were delivered, those rows stay in your dataset and the run is marked failed, so a partial export never looks complete.
Development
python3.12 -m venv .venv && source .venv/bin/activatepip install -r requirements.txtpython tests_logic.py # pure-logic tests (no network)apify validate-schemaapify run # local run (set storage/key_value_stores/default/INPUT.json)