React hooks and components for the UniRate currency-exchange API.
useExchangeRate(from, to)— single rateuseRates(from)— full rate table for a baseuseConvert(from, to, amount)— converted amountuseCurrencies()— list of supported codes (~600)useHistoricalRate(date, from, to)— historical rate (Pro)<Currency amount from to />— drop-in€92.50JSX<Rate from to />— drop-in1.0823JSX<UniRateProvider>— one client for the whole tree- Zero runtime deps. Native
fetch. AbortController cleanup on unmount.
npm install @unirate/react
# or
pnpm add @unirate/react
# or
yarn add @unirate/reactPeer dep: react ^18 || ^19. Requires Node 18.17+ for build/server use.
import{UniRateProvider,useExchangeRate,Currency}from"@unirate/react";functionApp(){return(<UniRateProviderapiKey={process.env.NEXT_PUBLIC_UNIRATE_API_KEY!}><Cart/></UniRateProvider>);}functionCart(){const{data: rate, isLoading }=useExchangeRate("USD","EUR");if(isLoading)return<p>Loading…</p>;return(<p>
1 USD = {rate} EUR. Your total:{" "}<Currencyamount={42.99}from="USD"to="EUR"/></p>);}Get a free API key at unirateapi.com — the free tier covers latest rates and conversions for ~600 currencies including crypto. Historical rates, time-series, and commodity feeds require Pro.
Every hook returns the same shape:
interfaceQueryState<T>{data: T|undefined;error: Error|undefined;isLoading: boolean;// true on the very first fetch onlyisFetching: boolean;// true on every refetch including the firstrefetch: ()=>void;// re-run the request manually}Every hook also accepts an options object:
{client?: UniRateClient;// override the provider's client
enabled?: boolean;// skip the fetch until true (default true)}const{ data, error, isLoading }=useExchangeRate("USD","EUR");// data: 0.92Returns the full rate table for a base.
const{ data }=useRates("USD");// data: { EUR: 0.92, GBP: 0.80, JPY: 154.21, ... }const{ data }=useConvert("USD","EUR",100);// data: 92.50const{data: codes}=useCurrencies();// data: ["USD", "EUR", "GBP", "JPY", "BTC", ...]Pro endpoint. Returns
ProRequiredErroron the free tier.
const{ data }=useHistoricalRate("2025-01-01","USD","EUR");// data: 0.851Renders one converted, locale-formatted amount.
<Currencyamount={1234.56}from="USD"to="EUR"/>// → "€1,141.97"<Currencyamount={100} to="EUR"loading="Converting…"/>// from defaults to "USD"; renders "Converting…" until the rate arrives<Currencyamount={100}from="USD"to="EUR"fallback={(err)=><spantitle={err.message}>n/a</span>}/>On error with no fallback prop, <Currency> falls back to the unconverted amount in the source currency so layouts don't collapse.
Renders a bare exchange-rate number.
<Ratefrom="EUR"to="USD"/>// → "1.0823"<Ratefrom="EUR"to="USD"decimals={2}/>//→"1.08"Putting an API key directly in client-side React means the key ships to every visitor's browser. For production deployments you have two options:
Proxy through your backend. Point
baseUrlat your own endpoint and have that endpoint hold the realUNIRATE_API_KEY:<UniRateProviderapiKey="placeholder"baseUrl="/api/unirate"/>
The placeholder still passes the client's "apiKey is required" check; your server inspects requests and inserts the real key before forwarding to
api.unirateapi.com.Free-tier-only public key. Free-tier UniRate keys are rate-limited per key; if a leaked key only unlocks endpoints you don't mind being shared, shipping it client-side is acceptable.
Server-only React (RSC, Remix loaders, server actions): you can use the raw UniRateClient directly without the provider, since there's no client component involved.
import{UniRateClient}from"@unirate/react/client";// in a server action / loader:constclient=newUniRateClient({apiKey: process.env.UNIRATE_API_KEY!});constrate=awaitclient.getRate("USD","EUR");The same error classes the hooks expose are also exported for instanceof checks:
AuthenticationError— 401, bad / missing keyRateLimitError— 429InvalidCurrencyError— 404, unknown currency codeInvalidRequestError— 400, bad paramsProRequiredError— 403, endpoint requires a Pro subscriptionUniRateError— base class for any other failure
const{ error }=useExchangeRate("USD","XYZ");if(errorinstanceofInvalidCurrencyError){return<p>Unsupported currency.</p>;}UniRate ships official integrations for 40+ ecosystems, all maintained under the UniRate-API org.
Core clients (9 languages)Python · Node.js / TypeScript · Go · Rust · Java · Ruby · PHP · .NET · Swift
JavaScript / TypeScriptReact · Next.js · Remix · SvelteKit · Vue · Angular · Nuxt · NestJS · tRPC
Static-site generatorsAstro · Eleventy · Hugo · Jekyll
CMS & e-commerceWagtail · WordPress · WooCommerce · Drupal · Strapi · Medusa · Symfony · Laravel · Directus
Data, AI & backendLangChain (Python) · LangChain.js · FastAPI · Flask · Django REST Framework · Apache Airflow · dbt
Platform & toolsMCP server · CLI · Cloudflare Workers · Home Assistant · n8n · Google Sheets · VS Code · Obsidian
Money library bridgesmoney gem (Ruby) · NodaMoney (.NET)
Get a free API key at unirateapi.com.
MIT © UniRate API