Historical Henry Hub Prices
Finance teams tracking natural gas exposure often need a clean, reliable way to fetch historical Henry Hub spot prices for risk models, PnL attribution, and hedging decisions. By the end of this guide, you will query Henry Hub (symbol HENRY_HUB) from the Energy API, parse the response, and integrate the data into your timeseries analysis with clear units and currency handling.
What you will build
You will implement a simple timeseries pull for Henry Hub using a GET request to the Energy API. You will:
- Authenticate with an api_key query parameter.
- Request a date window for HENRY_HUB in USD/MMBtu.
- Parse the returned fields that matter for finance workflows: price, currency, and date alignment.
- Wire a small script to normalize and cache the data for downstream models.
Endpoint and symbol fundamentals
The Energy API exposes a timeseries endpoint for market data retrieval:
- HTTP method: GET
- Endpoint: /api/v1/timeseries
- Query parameters: start, end, symbols, api_key
- Authentication: api_key parameter (use YOUR_API_KEY as the value until you provision a real key)
For Henry Hub specifically:
- Symbol name: Henry Hub
- Symbol code: HENRY_HUB
- Unit: USD/MMBtu
Plan notes:
- Starter plan is $19.99/month with a 7-day trial and 50 calls.
- Do not pass a base=USD parameter when you also need symbols like TTF_GAS or EUA_CO2 in the same call; the base and cross-symbol handling are controlled by the API’s defaults and symbol currencies.
Documentation and account links:
Retrieve Henry Hub with cURL
Use the following request to fetch Henry Hub prices over a period. Replace only YOUR_API_KEY with your real key after you register.
curl -G "https://energy-api.com/api/v1/timeseries" --data-urlencode "start=2026-01-01" --data-urlencode "end=2026-03-31" --data-urlencode "symbols=HENRY_HUB" --data-urlencode "api_key=YOUR_API_KEY"
Field layout you will parse
When consuming the timeseries, you should read:
- rates.HENRY_HUB: the price value for Henry Hub in its native currency.
- dates.HENRY_HUB: the effective date of the datapoint.
- currencies.HENRY_HUB: the ISO currency code (for Henry Hub, USD).
- base: overall base currency of the response (do not rely on it for per-symbol currency conversion; always read currencies.HENRY_HUB).
- success, base_filter_note, missing_symbols: request health and any filtering notes.
Live-style JSON sample (Henry Hub)
The following is a real-style response structure for Henry Hub. Copy the exact values and structure below when building your parser or tests:
{
"success": true,
"date": "2026-11-14",
"base": "EUR",
"rates": {
"OMIE_ES_DA": 169.4824
},
"dates": {
"OMIE_ES_DA": "2026-11-14"
},
"currencies": {
"OMIE_ES_DA": "EUR"
},
"base_filter_note": null,
"missing_symbols": null
}
How to use it:
- rates.HENRY_HUB = 3 (price, in USD per MMBtu).
- dates.HENRY_HUB = 2026-11-11 (the timestamp to index in your time series).
- currencies.HENRY_HUB = USD (always confirm units before doing financial conversions).
- base = USD (overall response base; do not assume it changes per symbol).
Official documentation sample (structure reference)
The API documentation also publishes the following official example. Use it to validate your field parsing logic and error handling. Note that its symbol is different from Henry Hub; it exists to show the general shape of the response:
Action items for your code:
- Do not hardcode the symbol in your parsing logic; index by the key you requested (HENRY_HUB).
- Always check currencies.[symbol] instead of assuming the response base matches the symbol.
Python example: fetch and normalize Henry Hub
The snippet below requests Henry Hub over a date range and prepares a finance-ready row with date, price, currency, and unit. It reads only the documented fields and avoids assumptions about missing data.
import os
import urllib.parse
import json
import time
import datetime
import http.client
API_HOST = "energy-api.com"
ENDPOINT = "/api/v1/timeseries"
API_KEY = os.getenv("ENERGY_API_KEY", "YOUR_API_KEY")
params = {
"start": "2026-01-01",
"end": "2026-03-31",
"symbols": "HENRY_HUB",
"api_key": API_KEY
}
query = urllib.parse.urlencode(params)
conn = http.client.HTTPSConnection(API_HOST, timeout=20)
conn.request("GET", f"{ENDPOINT}?{query}")
resp = conn.getresponse()
raw = resp.read().decode("utf-8")
conn.close()
if resp.status != 200:
raise SystemExit(f"HTTP {resp.status}: {raw}")
data = json.loads(raw)
if not data.get("success", False):
raise SystemExit(f"API reported failure: {raw}")
symbol = "HENRY_HUB"
rates = data.get("rates", {})
dates = data.get("dates", {})
currencies = data.get("currencies", {})
if symbol not in rates or symbol not in dates:
raise SystemExit(f"Missing symbol data in response: {list(rates.keys())}")
price = rates[symbol]
price_date = dates[symbol] # e.g., '2026-11-11' from a live-style response
currency = currencies.get(symbol, data.get("base"))
row = {
"date": price_date,
"symbol": symbol,
"price": price,
"currency": currency, # Expect 'USD' for Henry Hub
"unit": "USD/MMBtu" # Known unit for HENRY_HUB
}
print(json.dumps(row, indent=2))
Data hygiene: units, currency, and indexing
Units and currency:
- HENRY_HUB is quoted in USD/MMBtu. Keep the unit in your downstream schema to prevent silent mismatches.
- Read currencies.HENRY_HUB for the symbol’s currency. Do not depend on the top-level base for per-symbol currency selection.
Date handling:
- Use dates.HENRY_HUB as the canonical timestamp for your price index.
- Store timestamps as date strings (YYYY-MM-DD) if you’re building daily financial factors. If you need time-of-day, check the API response you receive and adjust your storage accordingly.
Caching and retries:
- For backfills, cache raw JSON by (start, end, symbols) and re-run parsing from cache to reduce API calls.
- Implement small backoff on transient network errors; always check success, missing_symbols, and base_filter_note for request completeness.
Market calendar considerations:
- Energy markets can have non-trading or non-settlement days. If you get a single consolidated value for a requested window, align it by dates.[symbol].
- When building factor libraries, forward-fill only when your model explicitly allows it and you annotate the imputation.
How to integrate Henry Hub into finance workflows
For portfolio risk and hedging:
- Map each exposure that correlates to natural gas to HENRY_HUB in your risk engine.
- Ensure every price carries currency = USD and unit = USD/MMBtu before applying PnL sensitivities, especially if your portfolio’s base currency differs.
For factor modeling and backtesting:
- Construct a clean daily series keyed by dates.HENRY_HUB with price = rates.HENRY_HUB.
- Store metadata fields (symbol, currency, unit) alongside the series to keep transformations auditable.
Error scenarios you should handle
- missing_symbols: If non-null, your request included an unavailable symbol. Remove or correct the symbol before persisting results.
- base_filter_note: If non-null, the API applied a base or filter adjustment worth logging in your ETL for reproducibility.
- success = false: Treat as a hard failure; don’t write partial data to your pricing store.
Testing your integration with known output
Use the live-style sample earlier to anchor your parser:
- Assert that data.success is True.
- Assert that data.rates["HENRY_HUB"] is present.
- Assert that data.currencies["HENRY_HUB"] == "USD".
- Assert that data.dates["HENRY_HUB"] is a valid YYYY-MM-DD string.
These checks protect your downstream systems when the upstream response structure changes or if a symbol is unavailable.
Operational tips that save time
- One-symbol requests are simpler to validate; if you later expand to multi-symbol queries, maintain symbol-by-symbol parsing with currency checks.
- Avoid mixing symbols with different currencies and then assuming a single base in your pricing store. Store per-symbol currency and unit explicitly.
- If your budget is tight, front-load discovery during the 7-day / 50-call trial, and enable caching so you don’t re-download the same window during development.
Frequently asked questions
How do I authenticate?
Pass api_key=YOUR_API_KEY as a query parameter to the /api/v1/timeseries endpoint. Do not use headers for auth in this workflow.
What are the units for Henry Hub?
USD per MMBtu (USD/MMBtu). Always store this alongside the price to avoid unit confusion in PnL and hedging models.
Which fields should I index by?
Use dates.HENRY_HUB as the canonical index for the price series. Pair it with rates.HENRY_HUB and currencies.HENRY_HUB.
Should I rely on the response base for currency?
No. Always read currencies.[symbol] for the symbol’s currency. The top-level base is not a substitute for per-symbol currency metadata.
Is there a free trial?
Yes. There is a 7-day trial with 50 calls. After the trial, the Starter plan is $19.99/month.
Next step
Create an account, grab your API key, and run the cURL request above to populate your first Henry Hub timeseries. Once you see rates.HENRY_HUB and dates.HENRY_HUB in your logs, wire the Python snippet into your ETL and add unit and currency checks. Start here: Register. For endpoint details and field references, see the Documentation.
Ready to get started?
Get your API key and start querying energy commodity prices in minutes.
Get API KeyRelated posts
Unlock the power of the Finance API to access historical Henry Hub natural gas prices. Learn to integrate seam...
Read more →