A natural gas price API returns a number like 2.850, and that number is meaningless until you know its unit. NATGAS, the natural gas symbol in SiftingIO's commodities feed, is quoted in US dollars per MMBtu (one million British thermal units), the standard unit for US wholesale gas pricing. That one fact answers most of the questions that come up when developers wire natural gas prices into a dashboard, a cost model, or a research dataset: why the price is a single-digit dollar figure, why it doesn't match a household utility bill, and why European gas prices look roughly three times bigger. This guide covers what NATGAS measures, what an MMBtu actually is, how to convert between MMBtu, therms, kilowatt-hours, and gigajoules, and the code to fetch historical bars and live prices.
What does NATGAS measure#
NATGAS is the US-dollar spot reference price for natural gas, expressed per MMBtu. Commodity symbols in the feed follow the USD-pair form used across the commodities data product: XAUUSD for gold, WTIUSD for crude oil, NATGAS for natural gas. The instrument's live detail page is the natural gas symbol page.
The published price is not a pass-through from one venue. SiftingIO aggregates quotes from multiple independent venues and publishes a single consensus value, formed as a volume- and reputation-weighted median. A median tolerates outliers: a stale print or a thin, off-market quote on one venue can't drag the published number, because a majority of venues would have to err in the same direction before the output moved. Every tick also carries source, ingest, and publish timestamps plus an explicit quality flag, so downstream code can tell a Normal tick from a Degraded one.
Two boundaries matter. First, the value is a synthetic reference price rather than an official exchange print, and it isn't executable depth; use it for charts, alerts, models, and sanity checks, never for order routing. Second, it's a wholesale benchmark. The rate a utility bills a household includes distribution, storage, and retail margin on top of the commodity itself, so NATGAS will not match anyone's gas bill.
MMBtu explained#
A British thermal unit (Btu) is the energy needed to raise one pound of water by one degree Fahrenheit. MMBtu means one million Btu. The double M comes from the Roman numeral M for thousand, so MM reads "a thousand thousands". You'll also see dekatherm (Dth), which is the same quantity under a different name, and therm, which is one tenth of it.
Natural gas trades by energy content instead of volume because the heat content of a cubic foot varies with the gas mix. Volume conversions are therefore approximate. The US Energy Information Administration's average heat-content figure is about 1,037 Btu per cubic foot, which puts one MMBtu near 964 cubic feet, or roughly 27.3 cubic meters.
| Unit | Definition | 1 MMBtu equals |
|---|---|---|
| MMBtu | 1,000,000 Btu | 1 |
| Dekatherm (Dth) | 1,000,000 Btu | 1 |
| Therm | 100,000 Btu | 10 therms |
| Kilowatt-hour (kWh) | 3,412.14 Btu | 293.07 kWh |
| Megawatt-hour (MWh) | 3,412,142 Btu | 0.29307 MWh |
| Gigajoule (GJ) | 947,817 Btu | 1.055056 GJ |
| Mcf (1,000 cubic feet) | ~1,037,000 Btu | ~0.964 Mcf |
Every row except Mcf is an exact physical definition (kWh rounded to two decimals). The Mcf row depends on gas composition, so treat it as an estimate.
How do you convert a natural gas price between units#
Take a last trade of 2.850 USD/MMBtu. Dividing or multiplying by the factors above converts the price into whatever unit the rest of your system uses:
| Target unit | Formula | Result at 2.850 USD/MMBtu |
|---|---|---|
| USD per therm | price / 10 | 0.2850 |
| USD per dekatherm | price × 1 | 2.850 |
| USD per kWh | price / 293.07 | 0.00972 |
| USD per MWh | price × 3.41214 | 9.72 |
| USD per GJ | price / 1.055056 | 2.70 |
The 2.850 figure is an arbitrary worked example; the arithmetic holds at any price level. Two of these conversions come up constantly. Power engineers and European market analysts quote gas in per-MWh terms, so the 3.412 factor bridges the two conventions: 2.85 USD/MMBtu is 9.72 USD/MWh. European benchmark prices are also quoted in euros, so a full comparison needs a currency leg as well. Both legs can come from the same API: divide the USD/MWh figure by the live EURUSD rate from /v1/last/quote/forex/EURUSD to land on EUR/MWh.
Fetching historical bars and live prices#
Historical natural gas bars come from the /v1/hist family. The historical endpoints require gzip, so send Accept-Encoding: gzip; curl's --compressed flag sets the header and decompresses the reply in one step:
curl --compressed -H "X-API-Key: $SIFTING_KEY" \
"https://api.sifting.io/v1/hist/commodities/NATGAS/bars?interval=1d&limit=200"
Bars are OHLCV with UTC timestamps, at intervals from 1m up to 1d. Pagination is cursor-based: pass limit (default 1000, max 2000) and follow meta.next_cursor until it comes back null. History depth depends on plan, from one month on the free tier to full history on Pro and above.
In Python, requests negotiates gzip on its own, which turns the conversion table into a three-line pandas exercise:
import pandas as pd
import requests
resp = requests.get(
"https://api.sifting.io/v1/hist/commodities/NATGAS/bars",
headers={"X-API-Key": "sft_your_key_here"},
params={"interval": "1d", "limit": 200},
)
resp.raise_for_status()
bars = pd.DataFrame(resp.json()["data"])
bars["close_per_therm"] = bars["c"] / 10
bars["close_usd_mwh"] = bars["c"] * 3.41214
bars["close_cents_kwh"] = bars["c"] / 293.07 * 100
For the current price, the /v1/last snapshot endpoints return the latest trade and the best bid and ask:
curl -H "X-API-Key: $SIFTING_KEY" \
"https://api.sifting.io/v1/last/trade/commodities/NATGAS"
The matching quote endpoint, /v1/last/quote/commodities/NATGAS, carries the symbol, bid and ask with sizes, and a Unix millisecond timestamp. If a dashboard needs continuous updates instead of polling, the same API key works over WebSocket at wss://stream.sifting.io/ws/v1; connection setup, keepalive rules, and reconnect handling for commodities are covered in the commodities streaming guide.
Common pitfalls#
The historical endpoints return 406 gzip_required when a request doesn't accept gzip. Plain curl without --compressed hits this immediately. Python's requests and the official SDKs send the header by default, which is why the exact same URL can fail in a terminal and work in a script.
Unit mixups are the classic natural gas bug, and they're silent. A price treated as USD/MWh when it's USD/MMBtu is wrong by a factor of 3.4; treated as USD/therm it's wrong by 10; compared against a European benchmark without converting both the energy unit and the currency, it's off by whatever EURUSD happens to be. A cheap guard is a magnitude assertion after every conversion step: if a per-MMBtu column jumps by a factor of three or ten with no market event behind it, suspect the conversion before the market.
Live snapshots can return 503 stale_snapshot when the freshest consensus tick is older than the freshness threshold, which shows up around quiet weekend and holiday stretches. The error body includes last_t and server_now, so the client can decide whether the last value is still usable for display. Treat it as "render with a stale badge and retry later" instead of as an outage.
The free tier includes a month of bar history and live snapshots with no credit card, enough to test every conversion in this post against real prices. Start building free