Blockchain Data Fetcher
Fetch on-chain blockchain metrics including transaction counts, active wallet addresses, network hash rate, gas fees, and mempool data from major blockchain data providers and node RPC endpoints for crypto market analysis.
Blockchain.info Market Data Acquisition Framework
This notebook defines a standardized protocol for interfacing with the Blockchain.info public REST API to retrieve on-chain metric data for a single chart via a single function call.
1. Dependency Installation
!pip install requests pandasRequirement already satisfied: requests in /usr/local/lib/python3.12/dist-packages (2.32.4) Requirement already satisfied: pandas in /usr/local/lib/python3.12/dist-packages (2.2.2) Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.12/dist-packages (from requests) (3.4.7) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.12/dist-packages (from requests) (3.11) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.12/dist-packages (from requests) (2.5.0) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.12/dist-packages (from requests) (2026.2.25) Requirement already satisfied: numpy>=1.26.0 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.0.2) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.9.0.post0) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.2) Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas) (2026.1) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)
2. Library Imports
import warnings
warnings.filterwarnings("ignore")
import requests
import pandas as pd
from datetime import datetimeCode Logic
warnings.filterwarnings("ignore"): Suppresses non-critical runtime warnings to maintain clean output.requests: Handles HTTP communication with the Blockchain.info public REST endpoint.pandas: Provides the DataFrame structure for tabular time-series data.datetime: Supplies datetime objects for date delta computation.
3. Available Chart Types
Blockchain.info exposes the following chart categories via the
https://api.blockchain.info/charts/{chart_name} endpoint.
Each chart_name value maps directly into the REST path.
3.1 Market Data
| Chart Name | Description |
|---|---|
market-price | Average USD market price across major exchanges |
market-cap | Total USD value of all circulating Bitcoin |
trade-volume | USD value of Bitcoin traded on major exchanges per day |
exchange-volume | Total BTC volume traded on major exchanges per day |
3.2 Blockchain Activity
| Chart Name | Description |
|---|---|
n-transactions | Total number of confirmed transactions per day |
n-unique-addresses | Number of unique addresses used per day |
n-transactions-per-block | Average number of transactions per block |
output-volume | Total BTC output volume per day |
estimated-transaction-volume | Estimated BTC transaction volume per day |
estimated-transaction-volume-usd | Estimated USD transaction volume per day |
3.3 Mining & Network
| Chart Name | Description |
|---|---|
hash-rate | Estimated network hash rate in GH/s |
difficulty | Current mining difficulty target |
miners-revenue | Total miner revenue (block reward + fees) in USD |
transaction-fees | Total BTC paid in transaction fees per day |
transaction-fees-usd | Total USD value of transaction fees per day |
cost-per-transaction | Miner revenue per transaction in USD |
n-orphaned-blocks | Number of orphaned blocks per day |
3.4 Supply & Distribution
| Chart Name | Description |
|---|---|
total-bitcoins | Total number of BTC in circulation |
utxo-count | Number of unspent transaction outputs |
bitcoin-days-destroyed | Measure of BTC economic activity (age × volume) |
average-block-size | Average block size in MB |
blocks-size | Total size of all blocks per day in MB |
df_fees = fetch_chart("transaction-fees-usd", START_DATE, END_DATE)
print("--- Average Transaction Fee (USD) ---")
display(df_fees.head())
df_fees.info()--- Average Transaction Fee (USD) ---
| timestamp | datetime | transaction_fees_usd | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 9.397140e+06 |
| 1 | 1704153600 | 2024-01-02 | 6.452516e+06 |
| 2 | 1704240000 | 2024-01-03 | 6.429705e+06 |
| 3 | 1704326400 | 2024-01-04 | 5.546797e+06 |
| 4 | 1704412800 | 2024-01-05 | 5.121602e+06 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 transaction_fees_usd 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
4. Configuration
START_DATE = "2024-01-01" # Format: YYYY-MM-DD
END_DATE = "2024-01-08" # Format: YYYY-MM-DD
BASE_URL = "https://api.blockchain.info/charts/{chart_name}"Code Logic
START_DATE / END_DATE: ISO 8601 date strings defining the retrieval window applied to all fetch calls below.BASE_URL: Public Blockchain.info chart endpoint. No API key is required. The{chart_name}placeholder is resolved at call time.
5. Data Extraction Function
The fetch_chart function performs a single HTTP GET request to the
Blockchain.info charts endpoint, maps the response to a standardized
schema, and applies precision-safe type casting.
def fetch_chart(chart_name, start_date, end_date):
start_dt = datetime.strptime(start_date, "%Y-%m-%d")
end_dt = datetime.strptime(end_date, "%Y-%m-%d")
days_diff = (end_dt - start_dt).days
url = BASE_URL.format(chart_name=chart_name)
params = {
"format": "json",
"start": start_date,
"timespan": f"{days_diff}days",
"sampled": "false",
}
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json().get("values", [])
if not data:
return pd.DataFrame()
column_name = chart_name.replace("-", "_")
df = pd.DataFrame({
"timestamp": [int(d["x"]) for d in data],
"datetime": pd.to_datetime([d["x"] for d in data], unit="s"),
column_name: [float(d["y"]) for d in data],
})
df = df.astype({"timestamp": "int64", column_name: "float64"})
df = df.drop_duplicates("timestamp").sort_values("timestamp", ignore_index=True)
return dfCode Logic
datetime.strptime(...): Parses ISO 8601 date strings into datetime objects for delta computation.(end_dt - start_dt).days: Derives the integer day span required by thetimespanparameter.BASE_URL.format(chart_name=chart_name): Resolves the{chart_name}placeholder using the provided chart identifier."format": "json": Instructs the API to return a structured JSON payload."start": start_date: Anchors the retrieval window to the specified start date."timespan": f"{days_diff}days": Defines the window width in days. The API returns all data points within this span in a single response — no pagination required."sampled": "false": Disables API-side data compression, ensuring all available data points are returned.response.raise_for_status(): Raises anHTTPErroron any non-2xx response code, surfacing failures immediately.response.json().get("values", []): Extracts the time-series array from the response envelope; defaults to an empty list if the key is absent.chart_name.replace("-", "_"): Converts the hyphenated chart name to a valid DataFrame column identifier (e.g.,market-price→market_price).[int(d["x"]) for d in data]: Extracts the Unix second timestamp from each data point dict.[float(d["y"]) for d in data]: Extracts the metric value from each data point dict.pd.to_datetime([...], unit="s"): Derives a human-readabledatetimecolumn from Unix second timestamps..astype({...}): Casts columns to typed numerics required for arithmetic computation..drop_duplicates("timestamp").sort_values(...): Removes duplicate timestamps and enforces chronological ordering.
6. Execution — One Call Per Chart Type
Each cell below demonstrates a single fetch call for one representative chart from each category defined in Section 3.
6.1 Market Data — Price
df_price = fetch_chart("market-price", START_DATE, END_DATE)
print("--- Market Price ---")
display(df_price.head())
df_price.info()--- Market Price ---
| timestamp | datetime | market_price | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 42249.69 |
| 1 | 1704153600 | 2024-01-02 | 44176.26 |
| 2 | 1704240000 | 2024-01-03 | 44958.98 |
| 3 | 1704326400 | 2024-01-04 | 42854.95 |
| 4 | 1704412800 | 2024-01-05 | 44190.10 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 market_price 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.2 Market Data — Trade Volume
df_volume = fetch_chart("trade-volume", START_DATE, END_DATE)
print("--- Trade Volume (USD) ---")
display(df_volume.head())
df_volume.info()--- Trade Volume (USD) ---
| timestamp | datetime | trade_volume | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 1.204915e+08 |
| 1 | 1704153600 | 2024-01-02 | 1.914118e+08 |
| 2 | 1704240000 | 2024-01-03 | 4.996471e+08 |
| 3 | 1704326400 | 2024-01-04 | 5.142611e+08 |
| 4 | 1704412800 | 2024-01-05 | 3.149481e+08 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 trade_volume 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.3 Blockchain Activity — Confirmed Transactions
df_txn = fetch_chart("n-transactions", START_DATE, END_DATE)
print("--- Confirmed Transactions Per Day ---")
display(df_txn.head())
df_txn.info()--- Confirmed Transactions Per Day ---
| timestamp | datetime | n_transactions | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 657752.0 |
| 1 | 1704153600 | 2024-01-02 | 367319.0 |
| 2 | 1704240000 | 2024-01-03 | 502749.0 |
| 3 | 1704326400 | 2024-01-04 | 482557.0 |
| 4 | 1704412800 | 2024-01-05 | 420884.0 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 n_transactions 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.4 Blockchain Activity — Unique Addresses
df_addr = fetch_chart("n-unique-addresses", START_DATE, END_DATE)
print("--- Unique Active Addresses Per Day ---")
display(df_addr.head())
df_addr.info()--- Unique Active Addresses Per Day ---
| timestamp | datetime | n_unique_addresses | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 624628.0 |
| 1 | 1704153600 | 2024-01-02 | 550846.0 |
| 2 | 1704240000 | 2024-01-03 | 677059.0 |
| 3 | 1704326400 | 2024-01-04 | 675009.0 |
| 4 | 1704412800 | 2024-01-05 | 645934.0 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 n_unique_addresses 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.5 Mining & Network — Hash Rate
df_hash = fetch_chart("hash-rate", START_DATE, END_DATE)
print("--- Network Hash Rate (GH/s) ---")
display(df_hash.head())
df_hash.info()--- Network Hash Rate (GH/s) ---
| timestamp | datetime | hash_rate | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 5.548140e+08 |
| 1 | 1704153600 | 2024-01-02 | 4.689073e+08 |
| 2 | 1704240000 | 2024-01-03 | 5.655523e+08 |
| 3 | 1704326400 | 2024-01-04 | 6.085056e+08 |
| 4 | 1704412800 | 2024-01-05 | 4.939634e+08 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 hash_rate 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.6 Mining & Network — Miner Revenue
df_revenue = fetch_chart("miners-revenue", START_DATE, END_DATE)
print("--- Miner Revenue (USD) ---")
display(df_revenue.head())
df_revenue.info()--- Miner Revenue (USD) ---
| timestamp | datetime | miners_revenue | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 | 5.087515e+07 |
| 1 | 1704153600 | 2024-01-02 | 4.351777e+07 |
| 2 | 1704240000 | 2024-01-03 | 4.994274e+07 |
| 3 | 1704326400 | 2024-01-04 | 5.174221e+07 |
| 4 | 1704412800 | 2024-01-05 | 4.291799e+07 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 8 entries, 0 to 7 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 8 non-null int64 1 datetime 8 non-null datetime64[ns] 2 miners_revenue 8 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 324.0 bytes
6.7 Mempool — Unconfirmed Transactions
df_mempool = fetch_chart("mempool-size", START_DATE, END_DATE)
print("--- Mempool Size (Unconfirmed Transactions) ---")
display(df_mempool.head())
df_mempool.info()--- Mempool Size (Unconfirmed Transactions) ---
| timestamp | datetime | mempool_size | |
|---|---|---|---|
| 0 | 1704067200 | 2024-01-01 00:00:00 | 82038643.0 |
| 1 | 1704068100 | 2024-01-01 00:15:00 | 83151660.0 |
| 2 | 1704069000 | 2024-01-01 00:30:00 | 82448230.0 |
| 3 | 1704069900 | 2024-01-01 00:45:00 | 82636299.0 |
| 4 | 1704070800 | 2024-01-01 01:00:00 | 82265967.5 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 673 entries, 0 to 672 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 673 non-null int64 1 datetime 673 non-null datetime64[ns] 2 mempool_size 673 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 15.9 KB
6.8 Supply — Total BTC in Circulation
df_supply = fetch_chart("total-bitcoins", START_DATE, END_DATE)
print("--- Total BTC in Circulation ---")
display(df_supply.head())
df_supply.info()--- Total BTC in Circulation ---
| timestamp | datetime | total_bitcoins | |
|---|---|---|---|
| 0 | 1704068978 | 2024-01-01 00:29:38 | 19586168.75 |
| 1 | 1704069091 | 2024-01-01 00:31:31 | 19586175.00 |
| 2 | 1704070161 | 2024-01-01 00:49:21 | 19586181.25 |
| 3 | 1704070760 | 2024-01-01 00:59:20 | 19586187.50 |
| 4 | 1704071678 | 2024-01-01 01:14:38 | 19586193.75 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1010 entries, 0 to 1009 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 1010 non-null int64 1 datetime 1010 non-null datetime64[ns] 2 total_bitcoins 1010 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 23.8 KB
6.9 Supply — UTXO Count
df_utxo = fetch_chart("utxo-count", START_DATE, END_DATE)
print("--- Unspent Transaction Output Count ---")
display(df_utxo.head())
df_utxo.info()--- Unspent Transaction Output Count ---
| timestamp | datetime | utxo_count | |
|---|---|---|---|
| 0 | 1704068978 | 2024-01-01 00:29:38 | 154349387.0 |
| 1 | 1704069091 | 2024-01-01 00:31:31 | 154348604.0 |
| 2 | 1704070161 | 2024-01-01 00:49:21 | 154349266.0 |
| 3 | 1704070760 | 2024-01-01 00:59:20 | 154353682.0 |
| 4 | 1704071678 | 2024-01-01 01:14:38 | 154355956.0 |
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1010 entries, 0 to 1009 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 timestamp 1010 non-null int64 1 datetime 1010 non-null datetime64[ns] 2 utxo_count 1010 non-null float64 dtypes: datetime64[ns](1), float64(1), int64(1) memory usage: 23.8 KB
Conclusion
This notebook provides a robust framework for retrieving various Bitcoin blockchain metrics from the Blockchain.info API. The fetch_chart function standardizes the data acquisition process, allowing for easy and consistent access to market data, blockchain activity, mining and network statistics, and supply and distribution metrics. This allows for rapid exploration and analysis of on-chain data for various research or analytical purposes.