Gold Price API: How to Get Real-Time & Historical Data
Whether you're building a fintech app, investment portfolio tracker, or e-commerce platform for precious metals, accessing accurate gold price data is essential. This comprehensive guide covers everything from integrating LBMA gold price APIs to working with historical data spanning over 50 years, with production-ready code examples in Python and JavaScript.
Gold has been a store of value for millennia, and today's digital economy demands precise, real-time access to gold pricing data. The London Bullion Market Association (LBMA) sets the global standard for gold pricing, with their twice-daily gold price fix serving as the benchmark for international gold trading.
Modern gold price APIs provide access to this authoritative data, along with historical prices dating back to 1968 when the two-tier gold pricing system was established. This guide will show you how to integrate gold price data into your applications, handle troy ounce conversions, work with the XAU currency code, and build robust solutions that scale.
1. Understanding Gold Pricing Standards
The LBMA Gold Price
The LBMA Gold Price is the global benchmark for gold pricing, determined through an electronic auction process twice daily (10:30 AM and 3:00 PM London time). This price is expressed in USD per troy ounce for gold of 995.0 fineness (99.5% purity).
Key Gold Pricing Facts
- Standard Unit: Troy ounce (31.1035 grams)
- Standard Purity: 995.0 fineness (99.5% pure gold)
- Pricing Currency: US Dollars (USD)
- ISO Currency Code: XAU (1 XAU = 1 troy ounce of gold)
- Fixing Times: 10:30 AM and 3:00 PM London time (weekdays)
- Historical Data: Available from 1968 to present
XAU Currency Code
XAU is the ISO 4217 currency code for gold. Unlike fiat currencies that represent legal tender, XAU represents one troy ounce of gold. When you see XAU/USD quoted at $2,050, it means one troy ounce of gold costs $2,050 US dollars.
| Symbol | Code | Represents | Example Price |
|---|---|---|---|
| XAU | Gold | 1 troy ounce | $2,050/oz |
| XAG | Silver | 1 troy ounce | $24.50/oz |
| XPT | Platinum | 1 troy ounce | $950/oz |
| XPD | Palladium | 1 troy ounce | $1,020/oz |
API Integration Tip: When working with precious metals APIs, always specify XAU as the currency code for gold, not "GOLD" or custom symbols. This ensures compatibility with ISO 4217-compliant systems.
2. LBMA Gold Price Data Sources
Primary vs Secondary Data Sources
When integrating gold price data, you have several options for data sources:
Direct LBMA Data
Data directly from LBMA or authorized distributors. Highest accuracy but typically requires licensing agreements and higher costs.
Pros: Most authoritative, legal compliance
Cons: Expensive, complex licensing
Aggregated APIs
APIs that aggregate LBMA data along with spot prices from major exchanges. More affordable with simpler integration.
Pros: Cost-effective, easy integration, historical data
Cons: Slight delays, need to verify accuracy
Data Update Frequency
Gold prices fluctuate continuously during trading hours. Consider your application's needs:
- Real-time (tick-by-tick): Required for trading platforms and professional trading tools. Updates every few seconds.
- Spot prices (1-5 min delay): Suitable for most financial applications, portfolio trackers, and investment apps.
- Daily LBMA fix: Adequate for long-term investment tracking, accounting purposes, and historical analysis.
- Hourly updates: Good balance for consumer-facing apps that display current gold prices.
Cost Consideration: Real-time gold price feeds can cost hundreds to thousands of dollars per month. For most applications, spot prices with 1-5 minute delays are sufficient and much more cost-effective.
3. Working with XAU/USD Exchange Rates
Understanding XAU/USD Pricing
XAU/USD is quoted as the price of one troy ounce of gold in US dollars. Unlike traditional currency pairs, XAU is treated as the base currency, and USD is the quote currency.
from decimal import Decimal
# Example: XAU/USD = 2050.50 means:
# 1 troy ounce of gold = $2,050.50 USD
# To calculate the cost of gold in different amounts:
xau_usd_rate = Decimal('2050.50')
# Cost of 10 grams of gold
grams_per_troy_oz = Decimal('31.1035')
cost_per_gram = xau_usd_rate / grams_per_troy_oz
cost_10_grams = cost_per_gram * Decimal('10')
print(f"Cost of 10 grams of gold: ${cost_10_grams:.2f}")
# Output: Cost of 10 grams of gold: $659.23
# Cost of 1 kilogram of gold
cost_1_kg = cost_per_gram * Decimal('1000')
print(f"Cost of 1 kilogram of gold: ${cost_1_kg:.2f}")
# Output: Cost of 1 kilogram of gold: $65,923.00
Converting XAU to Other Currencies
To display gold prices in currencies other than USD, you need both XAU/USD rate and the target currency exchange rate:
from decimal import Decimal
import requests
class GoldPriceConverter:
"""Convert gold prices between currencies."""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.unirateapi.com/v1"
def get_xau_price_in_currency(self, target_currency: str = 'USD') -> Decimal:
"""
Get the current price of 1 troy ounce of gold in the target currency.
Args:
target_currency: ISO currency code (e.g., 'EUR', 'GBP', 'JPY')
Returns:
Price per troy ounce in the target currency
"""
# Get current rates with XAU included
response = requests.get(
f"{self.base_url}/latest/USD",
params={'api_key': self.api_key},
timeout=5
)
response.raise_for_status()
data = response.json()
# XAU/USD rate (how many USD per troy ounce)
xau_usd = Decimal(str(data['rates']['XAU']))
# Price per oz in USD (invert the rate)
usd_per_oz = Decimal('1') / xau_usd
if target_currency == 'USD':
return usd_per_oz
# Get USD to target currency rate
usd_to_target = Decimal(str(data['rates'][target_currency]))
# Convert USD price to target currency
price_in_target = usd_per_oz * usd_to_target
return price_in_target
# Usage example
converter = GoldPriceConverter(api_key='your_api_key_here')
# Get gold price in different currencies
usd_price = converter.get_xau_price_in_currency('USD')
eur_price = converter.get_xau_price_in_currency('EUR')
gbp_price = converter.get_xau_price_in_currency('GBP')
print(f"Gold price: ${usd_price:.2f} USD")
print(f"Gold price: €{eur_price:.2f} EUR")
print(f"Gold price: £{gbp_price:.2f} GBP")
Important: XAU rates are often quoted as USD/XAU (inverted), showing how many troy ounces you get for $1. Always verify whether your API returns XAU/USD or USD/XAU and invert if necessary.
4. Accessing Historical Gold Data (1968-2026)
Why Historical Gold Data Matters
Historical gold price data is essential for:
- Portfolio performance tracking and backtesting investment strategies
- Financial reporting and accounting with accurate historical valuations
- Tax calculations for capital gains on gold holdings
- Price trend analysis and forecasting models
- Academic research and economic analysis
Fetching Historical Gold Prices
Here's how to retrieve historical gold prices for a specific date or date range:
import requests
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Dict, List
class GoldHistoricalData:
"""Access historical gold price data."""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.unirateapi.com/v1"
def get_price_for_date(self, date: str) -> Decimal:
"""
Get gold price for a specific date.
Args:
date: Date string in YYYY-MM-DD format
Returns:
Gold price in USD per troy ounce
"""
response = requests.get(
f"{self.base_url}/historical/{date}/USD",
params={'api_key': self.api_key},
timeout=5
)
response.raise_for_status()
data = response.json()
# XAU rate represents troy ounces per USD, so invert it
xau_rate = Decimal(str(data['rates']['XAU']))
usd_per_oz = Decimal('1') / xau_rate
return usd_per_oz
def get_price_range(
self,
start_date: str,
end_date: str
) -> Dict[str, Decimal]:
"""
Get gold prices for a date range.
Args:
start_date: Start date in YYYY-MM-DD format
end_date: End date in YYYY-MM-DD format
Returns:
Dictionary mapping dates to prices
"""
response = requests.get(
f"{self.base_url}/timeseries",
params={
'api_key': self.api_key,
'base': 'USD',
'start_date': start_date,
'end_date': end_date
},
timeout=10
)
response.raise_for_status()
data = response.json()
prices = {}
for date, rates in data['rates'].items():
xau_rate = Decimal(str(rates['XAU']))
prices[date] = Decimal('1') / xau_rate
return prices
# Usage examples
historical = GoldHistoricalData(api_key='your_api_key_here')
# Get gold price on a specific date
price_jan_2020 = historical.get_price_for_date('2020-01-15')
print(f"Gold price on Jan 15, 2020: ${price_jan_2020:.2f}/oz")
# Get price range for 2023
prices_2023 = historical.get_price_range('2023-01-01', '2023-12-31')
print(f"\nGold prices in 2023:")
print(f"Highest: ${max(prices_2023.values()):.2f}")
print(f"Lowest: ${min(prices_2023.values()):.2f}")
print(f"Average: ${sum(prices_2023.values()) / len(prices_2023):.2f}")
Data Availability: Historical gold price data is typically available from 1968 onwards when the two-tier gold market was established. Weekends and holidays will not have data; always implement fallback logic to use the last available trading day.
5. Troy Ounce Conversions and Weight Standards
Understanding Troy Ounce Measurements
The troy ounce system is different from the avoirdupois ounce used for everyday measurements. Understanding these conversions is critical for accurate precious metals pricing.
| Unit | Conversion | Common Use |
|---|---|---|
| 1 Troy Ounce | 31.1035 grams | Precious metals standard |
| 1 Gram | 0.032151 troy ounces | Jewelry, small amounts |
| 1 Kilogram | 32.1507 troy ounces | Gold bars, bulk trading |
| 1 Avoirdupois Ounce | 0.911458 troy ounces | NOT used for gold |
Weight Conversion Utility Class
from decimal import Decimal
class GoldWeightConverter:
"""Convert between different gold weight measurements."""
# Conversion constants
GRAMS_PER_TROY_OZ = Decimal('31.1035')
TROY_OZ_PER_KILOGRAM = Decimal('32.1507')
TROY_OZ_PER_GRAIN = Decimal('0.00208333')
@classmethod
def troy_oz_to_grams(cls, troy_oz: Decimal) -> Decimal:
"""Convert troy ounces to grams."""
return troy_oz * cls.GRAMS_PER_TROY_OZ
@classmethod
def grams_to_troy_oz(cls, grams: Decimal) -> Decimal:
"""Convert grams to troy ounces."""
return grams / cls.GRAMS_PER_TROY_OZ
@classmethod
def troy_oz_to_kg(cls, troy_oz: Decimal) -> Decimal:
"""Convert troy ounces to kilograms."""
return troy_oz / cls.TROY_OZ_PER_KILOGRAM
@classmethod
def kg_to_troy_oz(cls, kg: Decimal) -> Decimal:
"""Convert kilograms to troy ounces."""
return kg * cls.TROY_OZ_PER_KILOGRAM
@classmethod
def calculate_value(
cls,
weight: Decimal,
unit: str,
price_per_oz: Decimal
) -> Decimal:
"""
Calculate the value of gold based on weight.
Args:
weight: Amount of gold
unit: Weight unit ('troy_oz', 'grams', 'kg')
price_per_oz: Current price per troy ounce
Returns:
Total value in USD
"""
# Convert to troy ounces
if unit == 'troy_oz':
troy_oz = weight
elif unit == 'grams':
troy_oz = cls.grams_to_troy_oz(weight)
elif unit == 'kg':
troy_oz = cls.kg_to_troy_oz(weight)
else:
raise ValueError(f"Unknown unit: {unit}")
return troy_oz * price_per_oz
# Usage examples
converter = GoldWeightConverter()
# Current gold price
current_price = Decimal('2050.50')
# Calculate value of different weights
value_10g = converter.calculate_value(
Decimal('10'),
'grams',
current_price
)
print(f"Value of 10 grams of gold: ${value_10g:.2f}")
value_1kg = converter.calculate_value(
Decimal('1'),
'kg',
current_price
)
print(f"Value of 1 kilogram of gold: ${value_1kg:.2f}")
# Convert weights
print(f"\n10 grams = {converter.grams_to_troy_oz(Decimal('10')):.4f} troy oz")
print(f"1 kg = {converter.kg_to_troy_oz(Decimal('1')):.4f} troy oz")
Critical Error to Avoid: Never confuse troy ounces with avoirdupois ounces. A troy ounce (31.1g) is about 10% heavier than an avoirdupois ounce (28.35g). This mistake can lead to significant pricing errors in commercial applications.
6. Python Integration Examples
Complete Gold Price API Client
Here's a production-ready Python client for working with gold price APIs:
import requests
import redis
from decimal import Decimal
from datetime import datetime, timedelta
from typing import Optional, Dict
class GoldPriceAPI:
"""
Complete gold price API client with caching and error handling.
"""
def __init__(
self,
api_key: str,
redis_client: Optional[redis.Redis] = None,
cache_ttl: int = 3600
):
self.api_key = api_key
self.base_url = "https://api.unirateapi.com/v1"
self.redis = redis_client
self.cache_ttl = cache_ttl
self.session = requests.Session()
def get_current_price(self, currency: str = 'USD') -> Dict:
"""
Get current gold price in specified currency.
Returns:
Dict with price, timestamp, and metadata
"""
cache_key = f"gold:current:{currency}"
# Check cache
if self.redis:
cached = self.redis.get(cache_key)
if cached:
import json
return json.loads(cached.decode('utf-8'))
# Fetch from API
try:
response = self.session.get(
f"{self.base_url}/latest/USD",
params={'api_key': self.api_key},
timeout=5
)
response.raise_for_status()
data = response.json()
# Calculate price per troy ounce
xau_rate = Decimal(str(data['rates']['XAU']))
usd_per_oz = Decimal('1') / xau_rate
# Convert to target currency if needed
if currency != 'USD':
currency_rate = Decimal(str(data['rates'][currency]))
price = usd_per_oz * currency_rate
else:
price = usd_per_oz
result = {
'price': float(price),
'currency': currency,
'timestamp': data.get('timestamp', datetime.utcnow().isoformat()),
'unit': 'troy_ounce'
}
# Cache the result
if self.redis:
import json
self.redis.setex(
cache_key,
self.cache_ttl,
json.dumps(result)
)
return result
except requests.RequestException as e:
raise RuntimeError(f"Failed to fetch gold price: {e}")
def get_price_chart(
self,
days: int = 30,
currency: str = 'USD'
) -> Dict[str, Decimal]:
"""
Get historical prices for charting.
Args:
days: Number of days to retrieve
currency: Target currency
Returns:
Dictionary mapping dates to prices
"""
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
response = self.session.get(
f"{self.base_url}/timeseries",
params={
'api_key': self.api_key,
'base': 'USD',
'start_date': start_date.strftime('%Y-%m-%d'),
'end_date': end_date.strftime('%Y-%m-%d')
},
timeout=10
)
response.raise_for_status()
data = response.json()
prices = {}
for date, rates in data['rates'].items():
xau_rate = Decimal(str(rates['XAU']))
usd_per_oz = Decimal('1') / xau_rate
if currency != 'USD':
currency_rate = Decimal(str(rates[currency]))
prices[date] = usd_per_oz * currency_rate
else:
prices[date] = usd_per_oz
return prices
# Usage example
redis_client = redis.Redis(host='localhost', port=6379, db=0)
gold_api = GoldPriceAPI(
api_key='your_api_key_here',
redis_client=redis_client,
cache_ttl=1800 # 30 minutes
)
# Get current price
current = gold_api.get_current_price('USD')
print(f"Current gold price: ${current['price']:.2f} per troy ounce")
# Get 90-day price chart
chart_data = gold_api.get_price_chart(days=90, currency='USD')
print(f"\n90-day price range:")
print(f"High: ${max(chart_data.values()):.2f}")
print(f"Low: ${min(chart_data.values()):.2f}")
7. JavaScript Integration Examples
React Gold Price Component
A complete React component for displaying live gold prices:
import React, { useState, useEffect } from 'react';
const GoldPriceDisplay = ({ apiKey, currency = 'USD', refreshInterval = 60000 }) => {
const [price, setPrice] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [lastUpdate, setLastUpdate] = useState(null);
const fetchGoldPrice = async () => {
try {
const response = await fetch(
`https://api.unirateapi.com/v1/latest/USD?api_key=${apiKey}`
);
if (!response.ok) {
throw new Error('Failed to fetch gold price');
}
const data = await response.json();
// XAU rate is troy ounces per USD, so invert it
const xauRate = parseFloat(data.rates.XAU);
const usdPerOz = 1 / xauRate;
// Convert to target currency if needed
let finalPrice = usdPerOz;
if (currency !== 'USD') {
const currencyRate = parseFloat(data.rates[currency]);
finalPrice = usdPerOz * currencyRate;
}
setPrice(finalPrice);
setLastUpdate(new Date());
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchGoldPrice();
// Set up auto-refresh
const interval = setInterval(fetchGoldPrice, refreshInterval);
return () => clearInterval(interval);
}, [currency, refreshInterval]);
const formatCurrency = (amount, currencyCode) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currencyCode,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(amount);
};
if (loading) {
return (
Loading gold price...
);
}
if (error) {
return (
Error: {error}
);
}
return (
Gold (XAU)
per troy ounce
{formatCurrency(price, currency)}
Last updated: {lastUpdate?.toLocaleTimeString()}
);
};
export default GoldPriceDisplay;
Vanilla JavaScript Example
/**
* Simple gold price fetcher without dependencies
*/
class GoldPriceFetcher {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.unirateapi.com/v1';
this.cache = new Map();
this.cacheTTL = 1800000; // 30 minutes in milliseconds
}
async getCurrentPrice(currency = 'USD') {
const cacheKey = `gold_${currency}`;
const cached = this.cache.get(cacheKey);
// Return cached if still valid
if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
return cached.data;
}
try {
const response = await fetch(
`${this.baseUrl}/latest/USD?api_key=${this.apiKey}`
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Calculate price per troy ounce
const xauRate = parseFloat(data.rates.XAU);
let pricePerOz = 1 / xauRate;
// Convert to target currency
if (currency !== 'USD') {
const currencyRate = parseFloat(data.rates[currency]);
pricePerOz *= currencyRate;
}
const result = {
price: pricePerOz,
currency: currency,
timestamp: new Date().toISOString(),
unit: 'troy_ounce'
};
// Cache the result
this.cache.set(cacheKey, {
data: result,
timestamp: Date.now()
});
return result;
} catch (error) {
console.error('Error fetching gold price:', error);
throw error;
}
}
async getHistoricalPrice(date, currency = 'USD') {
try {
const response = await fetch(
`${this.baseUrl}/historical/${date}/USD?api_key=${this.apiKey}`
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const xauRate = parseFloat(data.rates.XAU);
let pricePerOz = 1 / xauRate;
if (currency !== 'USD') {
const currencyRate = parseFloat(data.rates[currency]);
pricePerOz *= currencyRate;
}
return {
price: pricePerOz,
currency: currency,
date: date,
unit: 'troy_ounce'
};
} catch (error) {
console.error('Error fetching historical gold price:', error);
throw error;
}
}
}
// Usage
const goldAPI = new GoldPriceFetcher('your_api_key_here');
// Get current price
goldAPI.getCurrentPrice('USD').then(data => {
console.log(`Current gold price: $${data.price.toFixed(2)} per oz`);
});
// Get historical price
goldAPI.getHistoricalPrice('2020-01-01', 'USD').then(data => {
console.log(`Gold price on Jan 1, 2020: $${data.price.toFixed(2)} per oz`);
});
8. Best Practices and Error Handling
Caching Strategy
Proper caching is essential for gold price APIs to reduce costs and improve performance:
Recommended Cache TTLs
- Current spot prices: 5-30 minutes (balance freshness vs API calls)
- Daily LBMA fix: 24 hours (updates only twice daily)
- Historical data: Permanent/indefinite (past data never changes)
- Price charts: 1 hour (unless real-time charting is required)
Error Handling
from typing import Optional
import logging
class GoldPriceError(Exception):
"""Base exception for gold price errors."""
pass
class APIConnectionError(GoldPriceError):
"""Raised when API connection fails."""
pass
class DataValidationError(GoldPriceError):
"""Raised when received data is invalid."""
pass
def fetch_gold_price_with_fallback(
api_client,
fallback_price: Optional[Decimal] = None
) -> Decimal:
"""
Fetch gold price with comprehensive error handling.
Args:
api_client: Gold price API client instance
fallback_price: Price to use if API fails
Returns:
Current gold price
Raises:
GoldPriceError if fetch fails and no fallback available
"""
max_retries = 3
for attempt in range(max_retries):
try:
result = api_client.get_current_price('USD')
price = Decimal(str(result['price']))
# Validate price is reasonable (between $500 and $10,000)
if not (Decimal('500') <= price <= Decimal('10000')):
raise DataValidationError(
f"Gold price ${price} is outside expected range"
)
return price
except requests.Timeout:
logging.warning(f"API timeout on attempt {attempt + 1}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
except requests.RequestException as e:
logging.error(f"API request failed: {e}")
except (KeyError, ValueError) as e:
raise DataValidationError(f"Invalid API response: {e}")
# All retries exhausted
if fallback_price:
logging.warning(f"Using fallback price: ${fallback_price}")
return fallback_price
raise APIConnectionError(
"Failed to fetch gold price after all retries"
)
Production Tip: Always implement graceful degradation. Store the last successful gold price and use it as a fallback if the API becomes unavailable. Display a warning to users that the price may be slightly outdated.
Rate Limiting
Most gold price APIs have rate limits. Implement proper rate limiting on your side:
- Use caching aggressively to minimize API calls
- Implement exponential backoff when hitting rate limits
- Queue requests during high traffic periods
- Monitor your API usage to avoid unexpected costs
- Consider upgrading to higher tiers if you consistently hit limits
Conclusion
Integrating gold price data into your application opens up possibilities for fintech apps, investment platforms, e-commerce stores, and financial analysis tools. The key to success is understanding the fundamentals: LBMA pricing standards, XAU currency codes, troy ounce measurements, and proper data handling.
With access to historical data back to 1968, you can build sophisticated analysis tools, accurate portfolio trackers, and reliable pricing systems. Always implement proper error handling, caching strategies, and fallback mechanisms to ensure your application remains stable even when external APIs experience issues.
Key Takeaways
- ✓ Use XAU as the ISO 4217 currency code for gold (1 XAU = 1 troy ounce)
- ✓ LBMA gold prices are the global benchmark, fixed twice daily
- ✓ 1 troy ounce = 31.1035 grams (not the same as avoirdupois ounce)
- ✓ Historical data from 1968 onwards is available for analysis
- ✓ Implement aggressive caching to minimize API costs
- ✓ Always validate price data and implement fallback mechanisms
Related Articles
Building a Precious Metals Price Tracker with Python
Learn how to track gold, silver, platinum, and palladium prices with Python, create price alerts, and visualize trends with matplotlib.
Multi-Currency Support for SaaS Applications
Complete guide to implementing multi-currency pricing, payment processing, and exchange rate management in SaaS platforms.
Access Gold Price Data with UniRate API
Get reliable gold price data with LBMA sources, historical data back to 1968, and support for all precious metals (XAU, XAG, XPT, XPD). Simple REST API with generous free tier and affordable pricing for commercial applications.
View API Pricing