7 min read

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.

Try the live API now →


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 window
  • X-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 →

C
Written by
Currency Converter Team
Financial Technology Experts

We are a team of financial technology developers dedicated to providing accurate, real-time currency conversion tools. Our mission is to make financial data accessible to everyone.