1 month free: no ads plus full access.

MetalCharts API examples

Requests you can copy and run for the things people most often build: a gold price in a chosen currency and unit, karat prices, a date range of history as CSV, a pandas DataFrame, and live prices in Google Sheets and Excel. Each one needs only a key, which is free for 200 requests a month.

Gold price per gram in euros, in Python

/v1/prices quotes in any of 32 currencies and six mass units. Ask for gold in euros per gram and the conversion is done for you at the ECB reference rate.
Python
import requests

res = requests.get(
    "https://api.metalcharts.org/v1/prices",
    params={"symbols": "XAU", "currency": "EUR", "unit": "g"},
    headers={"Authorization": "Bearer mc_live_YOUR_KEY"},
    timeout=10,
)
res.raise_for_status()

quote = res.json()["data"]["XAU"]
print(f"Gold: {quote['price']:.2f} EUR per gram")
Units are toz, g, kg, lb, mt and tola. Leave symbols out to get every metal in the same response.

22K, 18K or 14K gold price per gram, in any currency

Add karat and the response is gold at that purity. This is 22 karat gold in Indian rupees per gram; change the three values for 14K in dollars or 18K in dirhams.
JavaScript
const url = new URL("https://api.metalcharts.org/v1/prices");
url.search = new URLSearchParams({ symbols: "XAU", currency: "INR", unit: "g", karat: "22" });

const res = await fetch(url, { headers: { Authorization: "Bearer mc_live_YOUR_KEY" } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);

const { data } = await res.json();
console.log(`22K gold: ${data.XAU.price.toFixed(2)} INR per gram`);
Karat prices use nominal purity, the karat divided by 24, so 22K is 91.67 percent of the spot price. Native fetch runs in Node 18 and later; keep the key on your server.

What 10 grams of gold costs in euros

/v1/convert turns an amount of a metal, a currency or a unit into another. It answers questions like how much silver 1,000 rupees buys without any arithmetic on your side.
cURL
curl -H "Authorization: Bearer mc_live_YOUR_KEY" \
  "https://api.metalcharts.org/v1/convert?from=XAU&to=EUR&amount=10&unit=g"
The body carries result and the rate used. Add date=2025-01-15 to convert at that day's close.

Daily gold prices for a date range, as CSV

/v1/history/{symbol} takes a range such as 1M or 1Y, or a start and end date. Add format=csv and the same rows come back as a file a spreadsheet opens directly.
cURL
curl -H "Authorization: Bearer mc_live_YOUR_KEY" \
  "https://api.metalcharts.org/v1/history/XAU?start=2026-01-01&end=2026-01-31&interval=1d&format=csv" \
  -o gold-2026-01.csv
Each row has timestamp, open, high, low, close and volume. How far back a key can read depends on its plan: the free tier reaches 30 days, and Starter and Basic get the most recent year, Pro the most recent 5 years, and Ultimate and Enterprise all of it. Gold and silver daily bars start in October 1966.

Load gold price history into pandas

The history response is a list of bars, which is exactly what a DataFrame constructor wants.
Python
import pandas as pd
import requests

res = requests.get(
    "https://api.metalcharts.org/v1/history/XAU",
    params={"range": "1Y", "interval": "1d"},
    headers={"Authorization": "Bearer mc_live_YOUR_KEY"},
    timeout=30,
)
res.raise_for_status()

df = pd.DataFrame(res.json()["data"])
df["timestamp"] = pd.to_datetime(df["timestamp"])
df = df.set_index("timestamp")
print(df[["open", "high", "low", "close"]].tail())
Intervals run from 15m to 1M. Use XAG, XPT, XPD or HG in the path for silver, platinum, palladium or copper.

Gold price in Google Sheets with one formula

IMPORTDATA can't send a header, so put the key in the URL as api_key and ask for CSV. Row 2, column 2 of the result is the price. Anyone who can open the sheet can read the key in the formula, so don't use this in a sheet you share.
Google Sheets
=INDEX(IMPORTDATA("https://api.metalcharts.org/v1/prices?symbols=XAU&format=csv&api_key=mc_live_YOUR_KEY"), 2, 2)
Add &currency=EUR or &unit=g to the URL to change what is quoted, or drop INDEX to get the whole row. Sheets refetches IMPORTDATA about once an hour while the file is open, which can pass the free plan's 200 requests a month. The Apps Script version below caches for six hours and keeps the key out of the cells.

Gold price in Google Sheets, key kept private

This keeps the key in the script's settings, where people you share the sheet with can't see it. Open Extensions, then Apps Script, paste this, and save your key under Project Settings as a script property named METALCHARTS_KEY. Then type =METALPRICE("XAU") in a cell.
Apps Script
/**
 * =METALPRICE("XAU")              gold, US dollars per troy ounce
 * =METALPRICE("XAU", "EUR", "g")  gold, euros per gram
 */
function METALPRICE(symbol, currency, unit) {
  var key = PropertiesService.getScriptProperties().getProperty("METALCHARTS_KEY");
  var query = "?symbols=" + encodeURIComponent(symbol) +
    (currency ? "&currency=" + encodeURIComponent(currency) : "") +
    (unit ? "&unit=" + encodeURIComponent(unit) : "");

  var cache = CacheService.getScriptCache();
  var hit = cache.get(query);
  if (hit) return Number(hit);

  var res = UrlFetchApp.fetch("https://api.metalcharts.org/v1/prices" + query, {
    headers: { Authorization: "Bearer " + key },
    muteHttpExceptions: true,
  });
  if (res.getResponseCode() !== 200) {
    throw new Error("MetalCharts API returned " + res.getResponseCode());
  }

  var price = JSON.parse(res.getContentText()).data[symbol].price;
  cache.put(query, String(price), 21600); // six hours, the longest Apps Script allows
  return price;
}
The cache matters on the free tier of 200 requests a month: with a six-hour cache each distinct combination of symbol, currency and unit costs at most four requests a day, about 120 a month.

Gold and silver prices in Excel

Excel's Power Query can send the header. Choose Data, Get Data, From Other Sources, Blank Query, open the Advanced Editor and paste this. When Excel asks how to connect, pick Anonymous: the key is already in the header. Refresh the query to update the table.
Power Query (M)
let
    Source = Json.Document(
        Web.Contents(
            "https://api.metalcharts.org/v1/prices",
            [
                Query = [symbols = "XAU,XAG,XPT,XPD"],
                Headers = [Authorization = "Bearer mc_live_YOUR_KEY"]
            ]
        )
    ),
    Quotes = Record.ToTable(Source[data]),
    Expanded = Table.ExpandRecordColumn(Quotes, "Value", {"price", "changePercent24h", "timestamp"})
in
    Expanded
The result is one row per metal with its price, 24-hour change and timestamp. Add currency = "EUR" or unit = "g" inside Query to change what is quoted.

Stream live gold prices

/v1/stream/prices pushes each price as it changes, as Server-Sent Events over HTTPS. The first event is a snapshot of every requested metal; after that each change arrives as a price event. Gold, silver, platinum and palladium change every few seconds while the market is open.
Node.js 18+
const res = await fetch("https://api.metalcharts.org/v1/stream/prices?symbols=XAU,XAG", {
  headers: { Authorization: `Bearer ${process.env.METALCHARTS_API_KEY}` },
});

let buffer = "";
for await (const chunk of res.body.pipeThrough(new TextDecoderStream())) {
  buffer += chunk;
  let end;
  while ((end = buffer.indexOf("\n\n")) !== -1) {
    const block = buffer.slice(0, end);
    buffer = buffer.slice(end + 2);
    const data = block.split("\n").find((line) => line.startsWith("data: "));
    if (block.startsWith("event: price") && data) {
      const quote = JSON.parse(data.slice(6));
      console.log(quote.symbol, quote.price, quote.timestamp);
    }
  }
}
Included from the Pro plan with one connection; Ultimate holds 10 at once. The server closes a connection after an hour, so reconnect when the loop ends. From the shell: curl -N with the same header.

COMEX silver inventory, registered and eligible

The exchange endpoints return warehouse data most price APIs do not carry. This is the newest COMEX silver report with the previous day's figures beside it.
cURL
curl -H "Authorization: Bearer mc_live_YOUR_KEY" \
  "https://api.metalcharts.org/v1/comex/inventory?symbol=XAG&type=latest"
Needs the Pro plan or higher. Drop type and add range=1Y for the daily series; every response carries asOf, ageDays and a stale flag. The COMEX Inventory API page covers the rest.

FAQ

Common questions

Can I use IMPORTDATA or IMPORTJSON in Google Sheets?

Yes. Put the key in the URL as api_key and add format=csv, as in the one-formula example on this page. Anyone who can open the sheet can see a key in a formula, so for a shared sheet use the Apps Script function, which keeps the key in the script's settings and caches the result.

Is there a WebSocket or streaming endpoint?

Yes. /v1/stream/prices pushes prices as they change, as Server-Sent Events over HTTPS, from the Pro plan. Polling works on every plan: spot responses are cached for up to 30 seconds, and one request to /v1/prices returns every metal, so a backend that polls every 10 minutes uses about 4,300 requests a month.

Which examples work on the free tier?

Live prices, karat and currency quotes and conversions all work on the free tier of 200 requests a month, and history reaches 30 days back. Longer history and the exchange data (COMEX, LBMA, Shanghai, CFTC) need a paid plan.

Do I need an SDK?

No. Every endpoint is a GET request that returns JSON, and list endpoints return CSV with format=csv. The OpenAPI 3.0 document can generate a client in any language if you want one.

What symbols do the examples use?

Metals use their market codes: XAU for gold, XAG for silver, XPT for platinum, XPD for palladium and HG for copper. /v1/metals lists every supported metal.

Run these with your own key

A free key takes a minute and covers 200 requests a month. Every parameter and response field is in the API reference.