Blockchain Data Fetcher
Fetch on-chain metrics — hash rate, active addresses, transaction volume — from public blockchain APIs for use as trading signals.
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