Public data files
Read these snapshots without authentication or API keys. Data endpoints allow cross-origin GET, HEAD and OPTIONS with Access-Control-Allow-Origin: *; HTML pages do not. Shapes may change: check schema where present (charts.json currently has no schema field), and handle missing or null values.
| URL | Contents | Typical refresh / freshness fields |
|---|---|---|
/explorer-data.json | difficulty, height, finalized, finalization_lag, target_block_time and reward; windows.1h and windows.24h: blocks, avg_block_time, hashrate. | About 3 seconds. updated_at is Unix seconds; updated is an ISO date. |
/charts.json | series.24h, series.7d and series.30d contain timestamp, hashrate, difficulty, block_time and blocks. Buckets: 10 minutes, 1 hour and 4 hours. Check earliest and complete for coverage. | About 15 seconds. updated is Unix seconds. |
/pools.json | pools includes attribution, fees, blocks, share and work_share. unmapped is not necessarily the full list: read unmapped_truncated, unmapped_returned, unmapped_limit, unmapped_total_addresses and unmapped_total_blocks. | About 60 seconds. updated_at; also inspect each fee’s status, fetched_at and source. |
/growth.json | accounts tracks net accounts, including reaping; mining tracks cumulative mining emission, not total or circulating supply; circulating follows the supply exclusions. Each carries series. | About 60 seconds, with extra backfill updates. updated_at; accounts.status, circulating.status and circulating.expires_at. |
/vesting-data.json | schedules, pool_balance, total_scheduled, released and remaining, with the snapshot block. | About 60 seconds. updated_at; schedule times ending in _ms are milliseconds. |
/accounts-data.json | Top 100 accounts by total balance, total count and total_issuance at the finalized block; not a full account directory. | About 60 seconds plus sweep time. snapshot_at dates the observation; published_at dates publication. |
/miner-names.json | miners is keyed by reward address, with inferred name where available, share, lift and candidates. A name may be absent. | About 5 minutes from the telemetry publisher; the explorer polls every 3 seconds. Check updated_at. |
| Supply endpoints and methodology | Circulating, total and maximum supply, plus the computation snapshot. | See the supply documentation for refresh, expiry and error behavior. |
Reading the numbers
Intervals are typical, not guarantees. A successful read can be stale: compare timestamps with now, respect status and expires_at where supplied, and do not turn missing values into zero. Numeric timestamps are Unix seconds unless marked _ms. Hashrate is H/s; block times are seconds. Account, vesting and growth monetary integers are base-unit strings (QTC has 12 decimals); explorer-data.json reward is already in QTC.
Network hashrate is an estimate: sum of block difficulties divided by observed elapsed time across adjacent canonical blocks. It is not a measurement reported by miners. explorer-data.json carries this explanation in hashrate_note.
Read attribution.method and any status/note before quoting a pool’s blocks: block-hash, reported-height and report-timing matches are different evidence. Some records have null attribution and carry evidence/listing_note instead; do not infer a method from blocks alone. Fees and operator figures are self-reported. Pool matching methods.
Telemetry names are inferred from reporting behavior, not verified identities or operator declarations we endorse. share and lift describe the association; they do not prove ownership. Keep the reward address as the reference.
Example: current difficulty and estimated hashrate
JavaScript, usable from another origin. This example rejects data older than 180 seconds; choose a freshness policy for your use. It preserves the difficulty string and reads the one-hour estimate in H/s.
const response = await fetch(
'https://qtcscan.com/explorer-data.json',
{cache: 'no-store'}
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (data.schema !== 1) throw new Error('Unsupported schema');
if (!Number.isFinite(data.updated_at) ||
Date.now() / 1000 - data.updated_at > 180) {
throw new Error('Stale snapshot');
}
const hashrate = data.windows?.['1h']?.hashrate;
if (data.difficulty == null || !Number.isFinite(hashrate)) {
throw new Error('Missing metric');
}
console.log({
block: data.height,
difficulty: data.difficulty,
estimated_hashrate_h_s: hashrate,
observed_at: new Date(data.updated_at * 1000).toISOString()
});