
The goldprice.dev API returns the current spot price in a single authenticated GET request. This post walks through a minimal working implementation in both Node.js and the browser, then covers the error cases worth handling.
Get a free API key via the quickstart guide. The free tier includes 5,000 calls per month and gold, silver, and copper spot, 15 minutes late.
The endpoint
GET https://api.goldprice.dev/v1/spot/XAU-USD-SPOTAuthorization: Bearer ga_live_YOUR_KEYThe response is a flat JSON object:
{ "symbol": "XAU-USD-SPOT", "price": 2387.45, "currency": "USD", "unit": "troy_oz", "timestamp": "2026-06-19T08:32:11Z"}Node.js (18+)
Node 18 ships with the fetch API, so no extra dependencies are needed.
const API_KEY = process.env.GOLDPRICE_API_KEY;const BASE_URL = "https://api.goldprice.dev";async function getGoldSpot() { const res = await fetch(`${BASE_URL}/v1/spot/XAU-USD-SPOT`, { headers: { Authorization: `Bearer ${API_KEY}`, }, }); if (!res.ok) { const body = await res.text(); throw new Error(`API error ${res.status}: ${body}`); } return res.json();}getGoldSpot() .then((data) => { console.log(`Gold spot: $${data.price} USD/troy oz`); console.log(`As of: ${data.timestamp}`); }) .catch(console.error);Run it:
GOLDPRICE_API_KEY=ga_live_your_key node gold.jsNever hardcode the key string in source files. Reading it from process.env is the minimum safe approach; for production, use a secrets manager or environment injection at deploy time.
Browser
The same fetch API works in the browser with one caveat: your API key must not be exposed to the client. If you are building a public-facing app, proxy the request through your own backend. The browser code calls your server, and your server calls the goldprice.dev API with the key.
For internal tools, dashboards, or demos where key exposure is acceptable:
async function getGoldSpot(apiKey) { const res = await fetch("https://api.goldprice.dev/v1/spot/XAU-USD-SPOT", { headers: { Authorization: `Bearer ${apiKey}`, }, }); if (!res.ok) { throw new Error(`Request failed: ${res.status} ${res.statusText}`); } return res.json();}// UsagegetGoldSpot("ga_live_your_key").then((data) => { document.getElementById("gold-price").textContent = `$${data.price.toLocaleString()} USD/oz`;});Error handling
Three HTTP status codes cover almost every failure case:
401 Unauthorized: missing or invalidAuthorizationheader. Check that the key is present and starts withga_live_.429 Too Many Requests: rate limit exceeded. The response body includes aretry_afterfield in seconds. Back off and retry after that interval.5xx: server-side error. These are transient; retry with exponential backoff.
A more complete handler:
async function getGoldSpotSafe() { let attempt = 0; const maxAttempts = 3; while (attempt < maxAttempts) { const res = await fetch( "https://api.goldprice.dev/v1/spot/XAU-USD-SPOT", { headers: { Authorization: `Bearer ${process.env.GOLDPRICE_API_KEY}` }, } ); if (res.status === 401) { throw new Error("Invalid API key. Check GOLDPRICE_API_KEY."); } if (res.status === 429) { const body = await res.json(); const wait = (body.retry_after ?? 60) * 1000; await new Promise((r) => setTimeout(r, wait)); attempt++; continue; } if (!res.ok) { const delay = Math.min(1000 * 2 ** attempt, 10000); await new Promise((r) => setTimeout(r, delay)); attempt++; continue; } return res.json(); } throw new Error("Max retry attempts reached");}Caching on the free tier
With 5,000 calls per month, you have roughly 166 calls per day, enough for a polling interval of around 9 minutes. If you need to display a frequently refreshing price, cache the response on your server and serve it to your front end from there. A simple in-memory cache with a 60-second TTL is enough for most use cases:
let cache = null;let cacheTime = 0;const TTL_MS = 60_000;async function getCachedGoldSpot() { if (cache && Date.now() - cacheTime < TTL_MS) { return cache; } cache = await getGoldSpot(); cacheTime = Date.now(); return cache;}Paid plans provide live prices and higher monthly quotas. Keep caching and watch your rate-limit headers.
What's in the response
The price field is in USD per troy ounce. The timestamp is ISO 8601 in UTC. If you need the price in grams or other currencies, see Convert gold prices across currencies in code, that post covers the conversion arithmetic and a complete working example. The API documentation covers silver (XAG-USD-SPOT) and copper (HG-USD-SPOT), both available on every plan.
If you only need a price card on a website, use the free gold price widget instead. It is a hosted iframe with no browser-side API key, 31 currencies, gram and troy-ounce units, karat options, and built-in attribution.
Live gold prices, historical OHLC, and multi-source aggregation, available via REST and SSE.