Best Currency API for Google Sheets (2026)
Google Sheets is the go-to tool for finance teams, accountants, freelancers, and small businesses that need to work with multiple currencies. Whether you are building an invoice template, tracking international expenses, forecasting multi-currency revenue, or reconciling foreign transactions, you need reliable exchange rate data inside your spreadsheet.
The problem: Google Sheets has a built-in GOOGLEFINANCE function that looks like the obvious solution, but it is unreliable, limited to roughly 50 currencies, offers no SLA, and frequently returns #N/A errors at the worst possible moment. It was never designed for business-critical financial workflows.
This article compares the 5 best ways to get exchange rate data into Google Sheets in 2026, including dedicated APIs, add-ons, Apps Script integrations, and the native GOOGLEFINANCE function. Spoiler: AllRatesToday is the clear winner for spreadsheet users, with a Google Sheets add-on, full Apps Script support, real-time mid-market rates, and a free tier that requires no credit card.
Side-by-Side Comparison
Here is an honest look at how the top 5 options stack up for Google Sheets users:
| API | Google Sheets Add-on | Apps Script | Free Tier | Real-Time | Historical |
|---|---|---|---|---|---|
| AllRatesToday | Yes (official) | Full support | Free, no CC | Yes (60s) | Yes |
| Open Exchange Rates | No | Manual setup | 1,000 req/mo | Hourly | Paid only |
| Fixer.io | No | Manual setup | 100 req/mo | No (daily) | Paid only |
| GOOGLEFINANCE | Built-in | N/A | Free | Delayed 20 min+ | Limited |
| ExchangeRate-API | No | Manual setup | 1,500 req/mo | No (daily) | Paid only |
Key takeaway: AllRatesToday is the only option on this list that offers an official Google Sheets add-on, full Apps Script compatibility, real-time rates updated every 60 seconds, historical data on the free tier, and no credit card requirement.
1. AllRatesToday — Best Overall for Google Sheets
AllRatesToday was built API-first with spreadsheet users in mind. It provides a dedicated Google Sheets add-on that lets you pull real-time and historical exchange rates into any cell without writing a single line of code. For power users, the REST API works seamlessly with Google Apps Script and IMPORTDATA formulas.
Using the Google Sheets Add-on
Install the AllRatesToday add-on from the Google Workspace Marketplace, enter your API key, and start pulling rates directly into cells. The add-on supports:
- Real-time rates for 160+ currencies
- Historical rates for any past date
- Batch conversion across multiple currency pairs
- Auto-refresh on a schedule you control
Using IMPORTDATA with AllRatesToday
The simplest way to get a rate into a cell without an add-on is the IMPORTDATA formula with the AllRatesToday CSV endpoint:
=IMPORTDATA("https://allratestoday.com/api/v1/rates/csv?source=USD&target=EUR&apikey=YOUR_API_KEY") For multiple currencies at once:
=IMPORTDATA("https://allratestoday.com/api/v1/rates/csv?source=USD&target=EUR,GBP,JPY,CAD,AUD&apikey=YOUR_API_KEY") Tip: Store your API key in a named range (e.g., API_KEY) and reference it in formulas: =IMPORTDATA("https://allratestoday.com/api/v1/rates/csv?source=USD&target=EUR&apikey=" & API_KEY). This keeps your key in one place and makes it easy to update.
Google Apps Script — Custom Function
For maximum flexibility, write a custom Apps Script function that you can call like any built-in formula:
/**
* Fetches the real-time exchange rate from AllRatesToday.
* Usage: =GETRATE("USD", "EUR")
*
* @param {string} source - Source currency code (e.g., "USD")
* @param {string} target - Target currency code (e.g., "EUR")
* @return {number} The current exchange rate
* @customfunction
*/
function GETRATE(source, target) {
var API_KEY = PropertiesService.getScriptProperties().getProperty("ART_API_KEY");
var url = "https://allratestoday.com/api/v1/rates"
+ "?source=" + encodeURIComponent(source)
+ "&target=" + encodeURIComponent(target);
var options = {
"method": "get",
"headers": {
"Authorization": "Bearer " + API_KEY
},
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
return data.rate;
} Now you can use it in any cell:
=GETRATE("USD", "EUR")
=GETRATE("GBP", "JPY")
=GETRATE(A2, B2) // Reference cells for dynamic pairs Apps Script — Convert an Amount
/**
* Converts an amount from one currency to another using AllRatesToday.
* Usage: =CONVERTCURRENCY(1000, "USD", "EUR")
*
* @param {number} amount - Amount to convert
* @param {string} source - Source currency code
* @param {string} target - Target currency code
* @return {number} The converted amount
* @customfunction
*/
function CONVERTCURRENCY(amount, source, target) {
var rate = GETRATE(source, target);
return Math.round(amount * rate * 100) / 100;
} Apps Script — Fetch Historical Rates
/**
* Fetches the exchange rate for a specific historical date.
* Usage: =HISTORICALRATE("USD", "EUR", "2026-01-15")
*
* @param {string} source - Source currency code
* @param {string} target - Target currency code
* @param {string} date - Date in YYYY-MM-DD format
* @return {number} The exchange rate on that date
* @customfunction
*/
function HISTORICALRATE(source, target, date) {
var API_KEY = PropertiesService.getScriptProperties().getProperty("ART_API_KEY");
var url = "https://allratestoday.com/api/v1/historical-rates"
+ "?source=" + encodeURIComponent(source)
+ "&target=" + encodeURIComponent(target)
+ "&date=" + encodeURIComponent(date);
var options = {
"method": "get",
"headers": {
"Authorization": "Bearer " + API_KEY
},
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
return data.rate;
} Apps Script — Auto-Refresh Rates on a Schedule
/**
* Updates all exchange rates in the "Rates" sheet.
* Set this to run on a time-driven trigger (e.g., every hour).
*/
function refreshAllRates() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Rates");
var API_KEY = PropertiesService.getScriptProperties().getProperty("ART_API_KEY");
var pairs = [
["USD", "EUR"], ["USD", "GBP"], ["USD", "JPY"],
["USD", "CAD"], ["USD", "AUD"], ["USD", "CHF"]
];
for (var i = 0; i < pairs.length; i++) {
var url = "https://allratestoday.com/api/v1/rates"
+ "?source=" + pairs[i][0]
+ "&target=" + pairs[i][1];
var options = {
"method": "get",
"headers": { "Authorization": "Bearer " + API_KEY },
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
// Write to columns: A = source, B = target, C = rate, D = timestamp
sheet.getRange(i + 2, 1).setValue(pairs[i][0]);
sheet.getRange(i + 2, 2).setValue(pairs[i][1]);
sheet.getRange(i + 2, 3).setValue(data.rate);
sheet.getRange(i + 2, 4).setValue(new Date());
}
} Setting up auto-refresh: In Google Sheets, go to Extensions → Apps Script → Triggers, and create a time-driven trigger for refreshAllRates. You can set it to run every minute, every 5 minutes, hourly, or daily.
- Data source: Reuters/Refinitiv and interbank feeds
- Update frequency: Every 60 seconds (real-time)
- Currencies: 160+ including majors, minors, and exotics
- Rate type: Mid-market (no bank markup)
- Free tier: Available — no credit card required
- Google Sheets: Official add-on + Apps Script + IMPORTDATA
2. Open Exchange Rates
Open Exchange Rates has no Google Sheets add-on. You need to write your own Apps Script to call their API. The free tier gives you 1,000 requests per month but locks you to USD as the base currency, which is a problem if your spreadsheet tracks expenses in EUR or GBP.
// Apps Script for Open Exchange Rates
function getOXRRate(target) {
var APP_ID = "YOUR_APP_ID";
var url = "https://openexchangerates.org/api/latest.json?app_id=" + APP_ID;
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
return data.rates[target];
// Note: always returns rates relative to USD on free tier
} - Free tier: 1,000 requests/month, USD base only
- Update frequency: Hourly on free, more frequent on paid
- Google Sheets add-on: No
- Limitation: Free plan locked to USD as base currency; no add-on
3. Fixer.io
Fixer was acquired by APILayer and now offers a very restrictive free tier. At 100 requests per month with EUR-only base currency, it is barely usable for a single spreadsheet that refreshes daily. There is no Google Sheets add-on, and the free tier only supports HTTP (not HTTPS), which means your API key is sent in plain text.
// Apps Script for Fixer.io
function getFixerRate(source, target) {
var API_KEY = "YOUR_API_KEY";
// Note: free tier is HTTP only (insecure)
var url = "http://data.fixer.io/api/latest"
+ "?access_key=" + API_KEY
+ "&base=EUR" // Free tier: EUR base only
+ "&symbols=" + target;
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
return data.rates[target];
} - Free tier: 100 requests/month, EUR base only
- Update frequency: Daily
- Google Sheets add-on: No
- Limitation: Free plan uses HTTP (not HTTPS), EUR base only, 100 req/mo is nearly unusable
4. GOOGLEFINANCE Function (Built-in)
Google Sheets includes a built-in GOOGLEFINANCE function that can fetch currency rates. It looks convenient, but it has serious limitations that make it unsuitable for business-critical spreadsheets.
Basic usage
=GOOGLEFINANCE("CURRENCY:USDEUR")
=GOOGLEFINANCE("CURRENCY:GBPJPY")
=1000 * GOOGLEFINANCE("CURRENCY:USDEUR") Historical rate (unreliable)
=INDEX(GOOGLEFINANCE("CURRENCY:USDEUR", "close", DATE(2026,1,15)), 2, 2) Why GOOGLEFINANCE falls short
- No SLA: Google provides no guarantee that GOOGLEFINANCE will work. It returns
#N/Aerrors frequently, especially during high traffic. - Delayed data: Rates can be delayed by 20 minutes or more. There is no documentation on exactly how often they update.
- Limited currencies: Only ~50 currencies are supported. No exotic pairs.
- No API key: Because there is no authentication, there is no way to get support or guaranteed uptime.
- Cannot be used in Apps Script: GOOGLEFINANCE is a spreadsheet-only function. You cannot call it from Apps Script code.
- Breaks automation: If you build automations that depend on GOOGLEFINANCE values,
#N/Aerrors will propagate through your entire spreadsheet. - No batch endpoint: Each GOOGLEFINANCE call is independent. Getting rates for 20 currencies means 20 separate function calls that may or may not resolve.
When GOOGLEFINANCE is acceptable: Personal budgeting or quick one-off lookups where accuracy and reliability are not critical. For anything involving invoicing, accounting, financial reporting, or client-facing data, use a dedicated API.
5. ExchangeRate-API
ExchangeRate-API offers a simple REST endpoint with no Google Sheets add-on. The free tier gives 1,500 requests per month with daily-updated rates. You need to write your own Apps Script to integrate it.
// Apps Script for ExchangeRate-API
function getERApiRate(source, target) {
var API_KEY = "YOUR_API_KEY";
var url = "https://v6.exchangerate-api.com/v6/" + API_KEY + "/latest/" + source;
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
return data.conversion_rates[target];
} - Free tier: 1,500 requests/month
- Update frequency: Daily
- Google Sheets add-on: No
- Limitation: No real-time rates, historical data requires paid plan
Real-World Use Cases for Spreadsheet Users
Invoice template with auto-conversion
Build an invoice template that automatically converts line items to your client's currency:
// Cell setup:
// A1: "Invoice Currency" B1: "EUR"
// A2: "Your Currency" B2: "USD"
// A3: "Exchange Rate" B3: =GETRATE(B2, B1)
// A4: "Rate Updated" B4: =NOW()
// Line items:
// Column D (Amount USD) | Column E (Amount EUR)
// D6: 500 | E6: =D6 * $B$3
// D7: 1200 | E7: =D7 * $B$3
// D8: 350 | E8: =D8 * $B$3 Multi-currency expense tracker
/**
* Bulk-converts a column of amounts in various currencies to a single base currency.
* Designed for expense tracking sheets.
*
* @param {Range} amounts - Range of expense amounts
* @param {Range} currencies - Range of currency codes (same size as amounts)
* @param {string} baseCurrency - Your base/home currency
* @return {number[]} Array of converted amounts
* @customfunction
*/
function CONVERTEXPENSES(amounts, currencies, baseCurrency) {
var API_KEY = PropertiesService.getScriptProperties().getProperty("ART_API_KEY");
var results = [];
// Fetch all rates at once to minimize API calls
var url = "https://allratestoday.com/api/v1/rates?source=" + baseCurrency;
var options = {
"method": "get",
"headers": { "Authorization": "Bearer " + API_KEY },
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
var allRates = JSON.parse(response.getContentText()).rates;
for (var i = 0; i < amounts.length; i++) {
var amount = amounts[i][0];
var currency = currencies[i][0];
if (!amount || !currency) {
results.push([""]);
continue;
}
if (currency === baseCurrency) {
results.push([amount]);
} else {
// Convert: foreign amount / rate = base amount
var rate = allRates[currency];
results.push([Math.round((amount / rate) * 100) / 100]);
}
}
return results;
} Monthly exchange rate dashboard
/**
* Populates a dashboard with end-of-month rates for the current year.
* Run manually or on a monthly trigger.
*/
function buildMonthlyDashboard() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Dashboard");
var API_KEY = PropertiesService.getScriptProperties().getProperty("ART_API_KEY");
var baseCurrency = "USD";
var targets = ["EUR", "GBP", "JPY", "CAD", "AUD"];
// Headers
sheet.getRange(1, 1).setValue("Month");
for (var t = 0; t < targets.length; t++) {
sheet.getRange(1, t + 2).setValue(baseCurrency + "/" + targets[t]);
}
var year = new Date().getFullYear();
var currentMonth = new Date().getMonth(); // 0-indexed
for (var m = 0; m < currentMonth; m++) {
// Last day of each month
var lastDay = new Date(year, m + 1, 0);
var dateStr = Utilities.formatDate(lastDay, "UTC", "yyyy-MM-dd");
sheet.getRange(m + 2, 1).setValue(Utilities.formatDate(lastDay, "UTC", "MMM yyyy"));
for (var t = 0; t < targets.length; t++) {
var url = "https://allratestoday.com/api/v1/historical-rates"
+ "?source=" + baseCurrency
+ "&target=" + targets[t]
+ "&date=" + dateStr;
var options = {
"method": "get",
"headers": { "Authorization": "Bearer " + API_KEY },
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
sheet.getRange(m + 2, t + 2).setValue(data.rate);
}
}
} GOOGLEFINANCE vs. AllRatesToday: Head-to-Head
| Feature | GOOGLEFINANCE | AllRatesToday |
|---|---|---|
| Reliability | No SLA, frequent #N/A errors | 99.9% uptime SLA |
| Update speed | Delayed 20+ minutes | Every 60 seconds |
| Currencies | ~50 | 160+ |
| Apps Script | Not callable from script | Full REST API support |
| Historical data | Unreliable, limited | Complete, free tier |
| Rate type | Unknown source | Mid-market (Reuters/Refinitiv) |
| Add-on | Built-in function only | Official add-on |
| Support | None (community forums) | Email + documentation |
Why AllRatesToday Wins for Google Sheets
After comparing all five options, here is why AllRatesToday is the best choice for spreadsheet users:
- Official Google Sheets add-on: Install from the Workspace Marketplace and start pulling rates into cells immediately. No coding required for basic use cases.
- Full Apps Script support: Build custom functions like
=GETRATE("USD","EUR")and=CONVERTCURRENCY(1000,"USD","EUR")that work like native spreadsheet formulas. - IMPORTDATA compatible: Use the CSV endpoint with a simple formula for quick, no-code integration.
- Real-time rates: Updated every 60 seconds from Reuters/Refinitiv and interbank feeds. GOOGLEFINANCE is delayed 20+ minutes and the other APIs provide daily rates at best.
- Mid-market rates: The true interbank rate with no bank markup. This is the rate your accountant and auditors expect to see.
- 160+ currencies: Covers majors, minors, and exotic currency pairs. GOOGLEFINANCE only supports ~50.
- Historical data on free tier: Pull rates for any past date. Essential for month-end reconciliation and financial reporting. Most competitors lock this behind paid plans.
- No credit card required: Sign up and start building immediately. Open Exchange Rates and Fixer require payment information.
- Reliable: Unlike GOOGLEFINANCE, AllRatesToday provides a 99.9% uptime SLA. Your spreadsheets will not break with
#N/Aerrors.
Quick Reference
- Add-on: Install from Google Workspace Marketplace
- IMPORTDATA:
=IMPORTDATA("https://allratestoday.com/api/v1/rates/csv?source=USD&target=EUR&apikey=YOUR_API_KEY") - Apps Script: Use
UrlFetchApp.fetch()with Bearer token auth - Get rates:
GET /api/v1/rates?source=USD&target=EUR - Historical:
GET /api/v1/historical-rates?source=USD&target=EUR&date=2026-01-15 - Auth:
Authorization: Bearer YOUR_API_KEY
Get Exchange Rates in Google Sheets in 30 Seconds
Sign up for a free API key, install the Google Sheets add-on, and pull real-time mid-market rates for 160+ currencies into your spreadsheet. No credit card required. Compare all options on our Exchange Rate API page.
Get Your Free API Key