Currency Converter API for JavaScript — Free, No Key, CORS Enabled
Learn how to use the free Currency Exchange Tool API in JavaScript with fetch(). No API key, no signup, live mid-market rates. Full example with error handling and rate-limit awareness.
Currency Converter API for JavaScript — Free, No Key Required
Last updated: June 28, 2026 — Read time: 7 min
If you're building a web app and need live exchange rates, most APIs require signup, an API key, or a credit card. Not this one. The Currency Exchange Tool API is completely open — no registration, no auth, CORS enabled. Call it directly from browser JavaScript with fetch().
This guide covers everything you need: a basic converter, error handling, rate-limit awareness, and a complete currency dropdown component.
Why This API?
| Feature | This API | ExchangeRate-API | Fixer.io |
|---|---|---|---|
| API Key Required | No | Yes | Yes |
| Signup Required | No | Yes | Yes |
| CORS Enabled | Yes | No (proxy needed) | No |
| Currencies | 100+ | 160 | 170 |
| Monthly Limit | No cap | 1,500 | 100 |
| Rate Updates | Live | Daily | Daily |
Quick Start — 3 Lines of JavaScript
const res = await fetch(
'https://www.currencyexchangetool.com/api/v1/convert?amount=100&from=USD&to=EUR'
);
const data = await res.json();
console.log(`100 USD = ${data.result} EUR at rate ${data.rate}`);
That's it. No headers, no tokens, no SDK. Just a GET request.
Complete Converter Component
Here is a production-ready currency converter component in vanilla JavaScript:
class CurrencyConverter {
constructor() {
this.baseUrl = 'https://www.currencyexchangetool.com/api/v1';
}
async convert(amount, from, to) {
if (!amount || amount <= 0) throw new Error('Amount must be positive');
if (!from || !to) throw new Error('Both currencies are required');
const url = `${this.baseUrl}/convert?amount=${amount}&from=${from}&to=${to}`;
const res = await fetch(url);
// Check rate-limit headers
const remaining = res.headers.get('X-RateLimit-Remaining');
if (remaining === '0') {
const retryAfter = res.headers.get('Retry-After') || 60;
throw new Error(`Rate limited. Retry after ${retryAfter} seconds.`);
}
if (!res.ok) {
const err = await res.json();
throw new Error(err.error || `HTTP ${res.status}`);
}
const data = await res.json();
return {
from: data.from,
to: data.to,
amount: data.amount,
rate: data.rate,
result: data.result,
change24h: data.changePct24h,
updatedAt: new Date(data.updatedAt),
};
}
async getCurrencies() {
const res = await fetch(`${this.baseUrl}/currencies`);
const data = await res.json();
if (!data.success) throw new Error('Failed to fetch currencies');
return data.currencies;
}
}
Usage
const converter = new CurrencyConverter();
// Convert 500 USD to JPY
const result = await converter.convert(500, 'USD', 'JPY');
console.log(`500 USD = ${result.result} JPY (rate: ${result.rate})`);
// Get all available currencies
const currencies = await converter.getCurrencies();
console.log(`${currencies.length} currencies available`);
Building a Currency Selector Dropdown
Use the /api/v1/currencies endpoint to populate a <select> element:
async function populateCurrencySelector(selectElement) {
const res = await fetch(
'https://www.currencyexchangetool.com/api/v1/currencies'
);
const data = await res.json();
selectElement.innerHTML = '';
data.currencies.forEach(({ code, name }) => {
const option = document.createElement('option');
option.value = code;
option.textContent = `${code} — ${name}`;
selectElement.appendChild(option);
});
}
// Usage
const fromSelect = document.getElementById('fromCurrency');
const toSelect = document.getElementById('toCurrency');
await Promise.all([
populateCurrencySelector(fromSelect),
populateCurrencySelector(toSelect),
]);
Error Handling — Complete Pattern
The API returns a structured envelope. Always check success before using the result:
async function safeConvert(amount, from, to) {
try {
const res = await fetch(
`https://www.currencyexchangetool.com/api/v1/convert?amount=${amount}&from=${from}&to=${to}`
);
const data = await res.json();
if (!data.success) {
// API-level error (unsupported currency, rate not found, etc.)
console.error(`API error [${data.code}]: ${data.error}`);
return null;
}
return data;
} catch (err) {
// Network error or JSON parse failure
console.error('Network error:', err.message);
return null;
}
}
Common Error Codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | unsupported_currency |
The currency code is not supported |
| 404 | — | No rate available for this pair |
| 429 | rate_limited |
Too many requests — check Retry-After header |
| 500 | — | Internal server error |
React Example (useEffect + useState)
import { useState, useEffect } from 'react';
function useExchangeRate(from, to) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
async function fetchRate() {
setLoading(true);
const res = await fetch(
`https://www.currencyexchangetool.com/api/v1/convert?amount=1&from=${from}&to=${to}`
);
const json = await res.json();
if (!cancelled) {
setData(json);
setLoading(false);
}
}
fetchRate();
return () => { cancelled = true; };
}, [from, to]);
return { data, loading };
}
// Usage
function RateDisplay() {
const { data, loading } = useExchangeRate('USD', 'UAH');
if (loading) return <span>Loading...</span>;
return <span>1 USD = {data.result} UAH</span>;
}
Rate Limiting — Be a Good API Citizen
The API allows 100 requests per minute for convert and currencies endpoints. Every response includes headers to help you stay within limits:
X-RateLimit-Limit— maximum requests per window (100)X-RateLimit-Remaining— requests left in current windowX-RateLimit-Reset— seconds until the window resets
// Check rate limits before making a request
function checkRateLimit(headers) {
const remaining = parseInt(headers.get('X-RateLimit-Remaining'));
if (remaining < 5) {
console.warn(`Rate limit running low: ${remaining} requests left`);
}
}
Pro tip: For dashboard or polling use cases, cache the result for 60 seconds instead of calling the API on every render.
Google Sheets Integration
The same API works in Google Sheets with IMPORTXML:
=VALUE(IMPORTXML(
"https://www.currencyexchangetool.com/api/v1/convert?amount=1&from=USD&to=EUR&format=xml",
"/response/rate"
))
📖 Read the full API documentation → 💱 Open the free currency converter → 🔓 Why this API is different →