Copper, Aluminium, Zinc and Oil Prices via API: A Developer's Guide
Get copper, aluminium, zinc, steel, crude oil and natural gas prices via API: natural units, normalisation, front-month futures, conversions and code samples.
The industrial and energy symbols
Precious metals get most of the headlines, but many businesses care more about copper, aluminium, steel and fuel. These drive the cost of cables and motors, cans and car bodies, construction steel and every truck that moves goods. MetalAPI quotes four industrial metals and five energy contracts alongside gold and silver, through the same endpoints and in the same response format.
| Symbol | Market | Source | Natural unit |
|---|---|---|---|
XCU | Copper | COMEX copper front-month futures | USD per pound (lb) |
ALU | Aluminium | COMEX aluminium front-month futures | USD per metric ton |
ZNC | Zinc | COMEX zinc futures | USD per metric ton |
HRC | Hot-rolled coil steel | US Midwest HRC steel futures | USD per short ton |
WTI | WTI crude oil | NYMEX front-month futures | USD per barrel (bbl) |
BRENT | Brent crude oil | ICE front-month futures | USD per barrel (bbl) |
NATURALGAS | Natural gas | NYMEX Henry Hub futures | USD per MMBtu |
GASOLINE | Gasoline (RBOB) | NYMEX RBOB futures | USD per US gallon |
HEATINGOIL | Heating oil (ULSD) | NYMEX NY Harbor ULSD futures | USD per US gallon |
The symbols page lists them with live prices, and GET /api/v1/symbols?details=1 returns each symbol's category and unit as JSON. That call is free and does not count towards your quota.
Natural units vs the API's normalisation
Each of these markets has its own convention. In New York, copper trades per pound; aluminium and zinc trade per metric ton, US steel per short ton, crude oil per barrel, natural gas per million British thermal units (MMBtu) and refined products per gallon. Mix them up and your numbers are off by a factor of a thousand or more.
MetalAPI normalises the metals and leaves energy in its contract units:
- All metals, precious and industrial, are quoted per troy ounce by default. That keeps every metal directly comparable and lets you convert any of them with one parameter. Copper per troy ounce is not a number anyone trades, so for industrial metals you will almost always pass
unit. - Energy is quoted per contract unit: barrels for
WTIandBRENT, MMBtu forNATURALGAS, US gallons forGASOLINEandHEATINGOIL. Theunitparameter does not apply to energy, currencies or crypto.
unit accepts troy_oz (the default), gram, kilogram, ounce, pound, metric_ton and short_ton. To get each metal in the unit its market uses:
# Copper in USD per pound
curl "https://metalapi.com/api/v1/latest?currencies=XCU&unit=pound" \
-H "Authorization: Bearer YOUR_API_KEY"
# Aluminium and zinc in USD per metric ton
curl "https://metalapi.com/api/v1/latest?currencies=ALU,ZNC&unit=metric_ton" \
-H "Authorization: Bearer YOUR_API_KEY"
# Hot-rolled coil steel in USD per short ton
curl "https://metalapi.com/api/v1/latest?currencies=HRC&unit=short_ton" \
-H "Authorization: Bearer YOUR_API_KEY"When a non-default unit is used, the response says so in a unit field. The price you want is the key prefixed with the base currency (USDXCU); the plain XCU key is its inverse, kept for compatibility with older integrations:
{
"success": true,
"timestamp": 1792834892,
"date": "2026-10-24",
"base": "USD",
"unit": "pound",
"rates": {
"XCU": 0.2222222222,
"USDXCU": 4.5
}
}unit applies to every metal in the request. If you ask for XAU,XCU with unit=pound, gold comes back per pound too. Either make one request per unit, or fetch everything per troy ounce and convert in your own code, as shown below. Also note that ounce and oz mean the avoirdupois ounce (28.35 g), not the troy ounce.
Futures-based prices and what front-month means
Spot gold trades over the counter around the clock, but industrial metals and energy are priced most transparently on futures exchanges. MetalAPI takes these prices from COMEX and NYMEX (both part of CME Group) and from ICE. A futures contract is a standardised agreement to buy or sell a set quantity at a set price for delivery in a specific month. Each delivery month is a separate contract with its own price.
The front month is the nearest delivery month that is still trading. A continuous front-month series follows that contract until it approaches expiry and then switches, or rolls, to the next one. Three consequences matter for developers:
- Roll steps. On a roll date the series can jump, not because the market moved but because the next contract trades at a different price. When later months are more expensive (contango) the series steps up; when they are cheaper (backwardation) it steps down. Keep this in mind before alerting on a one-day change around expiry.
- One exchange is not the whole market. A COMEX copper price is a US exchange price. Much of the world's physical copper, aluminium and zinc is priced off the London Metal Exchange, and physical deliveries add regional premiums, freight and taxes. Prices on different venues track each other closely, but not exactly. If a supply contract names a specific reference, such as an LME official price or a published price assessment, that reference governs your invoice. An exchange futures feed is a good tool for monitoring and estimating, not a substitute for the contractual index.
- Trading hours. These contracts follow the hours of their exchanges: nearly around the clock from Sunday evening to Friday afternoon, New York time, with a short daily break. Over the weekend MetalAPI keeps returning the last price.
Because they come from futures, these symbols are published as a single price; bid and ask suffixes are not available for them. Daily history for metals and energy goes back to 2000, and the historical data guide shows how to query closing prices, ranges and OHLC bars.
Converting units and currencies
If you need several metals in different units, the cheapest approach is one request in troy ounces and the conversion in your own code. A data request counts once however many symbols it returns, so this costs one request instead of three. The constants below follow from the definitions of the units:
| Unit | Troy ounces | Other equivalents |
|---|---|---|
| 1 troy ounce | 1 | 31.1034768 g |
| 1 pound (lb) | 14.583333 | 453.59237 g |
| 1 kilogram | 32.150747 | 2.2046226 lb |
| 1 short ton | 29,166.667 | 2,000 lb; 907.18474 kg |
| 1 metric ton | 32,150.747 | 1,000 kg; 2,204.6226 lb |
// Troy ounces in one unit of mass
const GRAMS_PER_TROY_OZ = 31.1034768;
const TROY_OZ_PER = {
lb: 453.59237 / GRAMS_PER_TROY_OZ, // 14.5833…
short_ton: 907184.74 / GRAMS_PER_TROY_OZ, // 29,166.67…
metric_ton: 1e6 / GRAMS_PER_TROY_OZ, // 32,150.75…
};
const NATURAL_UNIT = { XCU: "lb", ALU: "metric_ton", ZNC: "metric_ton", HRC: "short_ton" };
const url = new URL("https://metalapi.com/api/v1/latest");
url.searchParams.set("currencies", Object.keys(NATURAL_UNIT).join(","));
const res = await fetch(url, { headers: { "X-API-Key": process.env.METALAPI_KEY } });
const data = await res.json();
if (!data.success) throw new Error(data.error.code + ": " + data.error.info);
for (const [symbol, unit] of Object.entries(NATURAL_UNIT)) {
const perTroyOz = data.rates["USD" + symbol]; // USD per troy ounce
if (perTroyOz === undefined) continue;
console.log(symbol, (perTroyOz * TROY_OZ_PER[unit]).toFixed(2), "USD per", unit);
}Currencies work the same way for metals and energy. Add base=EUR, or any of the 57 supported currencies, and every price in the response is expressed in that currency, converted from the same snapshot. To value a quantity directly, /convert takes an amount and a unit:
# 25 metric tons of copper in euros
curl "https://metalapi.com/api/v1/convert?from=XCU&to=EUR&amount=25&unit=metric_ton" \
-H "Authorization: Bearer YOUR_API_KEY"Energy conversions happen in your code. Useful standard factors: one barrel is 42 US gallons or about 158.987 litres; one US gallon is 3.785411784 litres; one MMBtu is about 1.055 gigajoules, 293.07 kWh or 10 therms. Converting barrels of crude oil to tonnes depends on the oil's density, so use the factor for the grade you actually buy.
Use case: procurement and cost monitoring
Procurement teams use exchange prices to understand where input costs are moving and to sanity-check supplier quotes. Typical building blocks:
- A daily dashboard of copper, aluminium, steel and diesel in the units and currency your contracts use.
- Period-over-period change with
/change, which returns the start price, end price, absolute change and percentage change between two dates for each symbol in one request. - Threshold alerts. On paid plans, price alerts in the dashboard send an email, and from the Advanced plan also a signed webhook, when a price crosses a level or moves by a percentage. That is a simple way to trigger a review of a budget assumption.
- Quote checks. Comparing the metal content of a supplier's price with the exchange reference shows how much of a price change comes from the metal and how much from premiums or processing.
# Copper and aluminium per metric ton: change over September 2026
curl "https://metalapi.com/api/v1/change?currencies=XCU,ALU&unit=metric_ton&start_date=2026-09-01&end_date=2026-09-30" \
-H "Authorization: Bearer YOUR_API_KEY"Keep the earlier caveat in mind: if a contract is indexed to a specific published price, reconcile against that index for anything that ends up on an invoice.
Use case: manufacturing cost models
A bill of materials usually lists metal content in kilograms. Because unit accepts kilogram for every metal, one request returns the price per kilogram for all of them, in your reporting currency:
import os
import requests
# Metal content per unit of product, in kg (illustrative)
BOM = {"XCU": 1.20, "ALU": 0.85, "ZNC": 0.05}
resp = requests.get(
"https://metalapi.com/api/v1/latest",
params={"currencies": ",".join(BOM), "unit": "kilogram", "base": "EUR"},
headers={"X-API-Key": os.environ["METALAPI_KEY"]},
timeout=10,
)
data = resp.json()
if not data.get("success"):
raise RuntimeError(data["error"])
total = 0.0
for symbol, kg in BOM.items():
eur_per_kg = data["rates"]["EUR" + symbol]
cost = kg * eur_per_kg
total += cost
print(f"{symbol}: {kg} kg x {eur_per_kg:.4f} EUR/kg = {cost:.2f} EUR")
print(f"Metal content per unit: {total:.2f} EUR (prices of {data['date']})")Two refinements make a model like this more useful. First, store the price, unit and timestamp you used next to each cost calculation, so you can explain later why a cost changed. Second, consider an average over a period instead of a single latest price; it smooths out daily noise and roll steps. /timeframe returns daily closes for up to 365 days per request on paid plans (30 days on Free), which is enough for a monthly or quarterly average in one call.
Use case: logistics and fuel costs
Fuel is the largest variable cost for many carriers, and fuel surcharges are often recalculated weekly or monthly. HEATINGOIL, the NY Harbor ultra-low-sulphur diesel contract, is a widely watched wholesale diesel reference. GASOLINE (RBOB) plays the same role for petrol, and WTI and BRENT cover crude oil.
Wholesale futures and pump prices are different things: retail prices add distribution costs, margins and taxes, and they follow futures with a lag. Many surcharge schedules reference a published retail average, and if yours does, that average is the number to use. Futures data is still useful for internal cost tracking and for seeing upstream moves early.
This example averages last week's daily closes of the diesel contract and converts the result from USD per gallon to EUR per litre:
const LITRES_PER_GALLON = 3.785411784;
const url = new URL("https://metalapi.com/api/v1/timeframe");
url.searchParams.set("currencies", "HEATINGOIL");
url.searchParams.set("base", "EUR");
url.searchParams.set("start_date", "2026-10-19");
url.searchParams.set("end_date", "2026-10-23");
const res = await fetch(url, { headers: { "X-API-Key": process.env.METALAPI_KEY } });
const data = await res.json();
if (!data.success) throw new Error(data.error.code + ": " + data.error.info);
// rates is keyed by date; days without a close (weekends, holidays) are missing
const closes = Object.values(data.rates).map((day) => day.EURHEATINGOIL);
const avgPerGallon = closes.reduce((sum, p) => sum + p, 0) / closes.length;
console.log("Average:", (avgPerGallon / LITRES_PER_GALLON).toFixed(4), "EUR per litre");Practical tips
- Poll at your plan's interval, not faster. Free sees daily prices, Lite every 30 minutes, Standard every 10 minutes, Advanced and Pro every minute, Ultra and Business every 15 seconds and Enterprise every 5 seconds. Requests in between return the same snapshot and still count. From Pro upward, the realtime stream replaces polling.
- Batch symbols. One request can return all nine industrial and energy symbols, and it costs the same as a request for one.
- Store what you fetched. Persist each price with its symbol, unit, base currency and
timestamp. Converting later is easy; guessing the unit of an old number is not. - Expect gaps in history. Daily series skip weekends and exchange holidays, so don't assume one entry per calendar day.
- Chunk long ranges. A single
/timeframerequest covers up to 365 days on paid plans, so loop year by year for longer histories back to 2000. - Validate before you send. Requests rejected for invalid dates, symbols or units still count towards your quota, so check them in your code first. Rate-limit rejections and server errors are not billed.
To get started, register for a free key, check the symbols page for live industrial and energy prices, and see the API docs for every endpoint and parameter. The pricing page lists the update interval and quota of each plan.
Try it with your own data
Create a free account and make your first request in under two minutes. 100 requests a month, no credit card.
Keep reading
Connect Claude and ChatGPT to Live Gold Prices with MCP
Connect Claude, ChatGPT, Cursor and VS Code to live gold and metal prices with the MetalAPI MCP server: OAuth or API key setup, tools, safety and quotas.
Spot, Bid, Ask and Spread: How Precious Metal Prices Are Quoted
What spot, bid, ask, mid and spread mean for gold, silver, platinum and palladium, how dealers build quotes, and how to request and display bid/ask via API.
How to Choose a Precious Metals Price API: 12 Questions to Ask
A vendor-neutral checklist for choosing a precious metals price API: sources, freshness, history, units, bid/ask, limits, pricing, security, terms and MCP.