Build a Gold Portfolio Tracker in Google Sheets
Import a ready-to-use gold portfolio tracker into Google Sheets, update one live price cell, and calculate indicative value, cost, and change by holding.
Read →Fetch gold prices per gram in Python without an API key, then calculate 24K, 22K, and 18K values safely with Decimal across 31 currencies.
If your application needs a gold price per gram, do not fetch a price per troy ounce and hide the conversion in presentation code. Request the per-gram purity ladder directly from the public /v1/carat endpoint.
One request returns 24K, 22K, 21K, 20K, 18K, 16K, 14K, and 10K metal values in the currency you choose. The endpoint is free to try and does not require an API key.
This example uses only the Python standard library. It requests the current values in euros and parses each price as Decimal so later money arithmetic does not introduce binary floating-point drift.
import json
from decimal import Decimal
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
BASE_URL = "https://api.goldprice.dev/v1/carat"
def gold_price_per_gram(currency: str = "EUR") -> dict[str, Decimal | str]:
query = urlencode({"currency": currency.upper()})
request = Request(
f"{BASE_URL}?{query}",
headers={"Accept": "application/json"},
)
try:
with urlopen(request, timeout=10) as response:
payload = json.load(response)
except HTTPError as error:
raise RuntimeError(f"Gold API returned HTTP {error.code}") from error
except URLError as error:
raise RuntimeError(f"Could not reach the Gold API: {error.reason}") from error
return {
"currency": payload["currency"],
"timestamp": payload["timestamp"],
"24k": Decimal(payload["price_gram_24k"]),
"22k": Decimal(payload["price_gram_22k"]),
"18k": Decimal(payload["price_gram_18k"]),
"14k": Decimal(payload["price_gram_14k"]),
}
prices = gold_price_per_gram("EUR")
print(f'24K: {prices["24k"]} {prices["currency"]}/g')
print(f'22K: {prices["22k"]} {prices["currency"]}/g')
print(f'18K: {prices["18k"]} {prices["currency"]}/g')
print(f'Observed: {prices["timestamp"]}')
Change EUR to any supported three-letter currency code, such as USD, GBP, INR, IDR, AED, or JPY. The same request shape works across the full 31-currency catalog.
The response contains one price field for each supported purity:
{
"currency": "EUR",
"timestamp": "2026-09-22T08:30:00Z",
"price_gram_24k": "120.16",
"price_gram_22k": "110.14",
"price_gram_21k": "105.14",
"price_gram_20k": "100.13",
"price_gram_18k": "90.12",
"price_gram_16k": "80.11",
"price_gram_14k": "70.09",
"price_gram_10k": "50.07"
}
The numbers above illustrate the response shape; fetch the endpoint for current values. Price fields are JSON strings on purpose. Read them with Decimal, not float, when you multiply by weights or store monetary results.
The endpoint name uses carat, while the response uses labels such as 24k and 18k. Both spellings appear in gold markets, but karat is the usual term for gold purity and carat is also used in some countries.
To estimate the metal value of a 12.5 gram, 18K item, multiply the returned 18K per-gram price by its weight:
from decimal import Decimal, ROUND_HALF_UP
weight_grams = Decimal("12.5")
metal_value = (weight_grams * prices["18k"]).quantize(
Decimal("0.01"),
rounding=ROUND_HALF_UP,
)
print(f"Indicative metal value: {metal_value} {prices['currency']}")
The endpoint already expresses each per-gram value at the requested currency's minor-unit precision. Keep that value as Decimal and round the final item value once. If a large-weight calculation needs sub-minor-unit precision per gram, start from the ounce price and apply the conversion formula before the final rounding step.
This result is the spot-derived value of the gold content. It is not automatically the retail price or the cash amount a buyer will offer. Jewellery making charges, gemstones, taxes, dealer premiums, refining costs, and buyback discounts are separate.
The calculation has three steps:
31.1034768 grams.22 / 24 for 22K or 18 / 24 for 18K.In compact form:
price per gram by karat
= gold price per troy ounce in the chosen currency
/ 31.1034768
* karat / 24
Calling /v1/carat keeps this conversion in one documented boundary. Your application receives the purity ladder from one observation instead of repeating unit and purity arithmetic in every client.
The first request does not need a key. That is useful for a local script, prototype, or one-off spreadsheet refresh. For a deployed application, create a free account and send the key from your server so usage belongs to your account rather than a shared anonymous limit.
import os
api_key = os.environ["GOLDPRICE_API_KEY"]
request = Request(
f"{BASE_URL}?{urlencode({'currency': 'EUR'})}",
headers={
"Accept": "application/json",
"Authorization": f"Bearer {api_key}",
},
)
Never put an account key in browser JavaScript or commit it to source control. Keep it in a server-side environment variable and handle non-2xx responses before reading the body as a successful price.
Decimal through the calculation.timestamp with the value.For the complete field contract, see the karat gold price API documentation. If you need daily OHLC history instead of a current per-gram value, use the historical gold price API.
related guides
Import a ready-to-use gold portfolio tracker into Google Sheets, update one live price cell, and calculate indicative value, cost, and change by holding.
Read →Learn how a live gold price chart combines spot quotes, OHLC bars, UTC timestamps, and controlled polling, with a working TypeScript SVG example.
Read →Build a live India gold-rate app from INR per-gram 24K and 22K prices, with server-side caching, Indian number formatting, GST estimates, and clear limits.
Read →goldprice.dev
Live gold prices, historical OHLC, and multi-source aggregation — available via REST and SSE.