Exchange rate provider layer for PHP. Direct access to 30 provider implementations through a single
ExchangeRateServiceinterface, with chain fallback and PSR-16 caching. Maintained since 2016.
Exchanger is the exchange rate provider layer for PHP. It exposes 30 services (the European Central Bank, several national banks, exchangerate.host, and commercial exchange rate APIs that require an API key) behind a single ExchangeRateService interface, with chainable fallback, PSR-16 caching, and historical rates. Used in real-world PHP applications since 2016.
For most use cases, the higher-level Swap library is what you want. Reach for Exchanger directly when you need finer control.
- Exchanger is a PHP library for currency conversion and exchange rate retrieval at the provider layer.
- It contains 30 service implementations behind a common
ExchangeRateServiceinterface. - It caches results via PSR-16 SimpleCache.
- It supports historical rates.
- It supports a chain service for fallback. When a service errors, the next one in the chain is tried.
- Use Exchanger when you need finer control than Swap exposes: custom chain composition, custom caching strategy, custom HTTP middleware, or building your own facade or framework integration.
- For most PHP applications, use Swap instead. It is built on Exchanger and provides sensible defaults and a builder-style API.
Swap is the easy-to-use, high-level API. Exchanger is the layer Swap is built on.
Reach for Exchanger directly when:
- Custom facade: you want to build your own currency conversion API on top of the provider layer.
- Framework binding: you are integrating into a framework that does not yet have a Swap binding.
- Fine-grained chain composition: you need to wrap services with custom logic (rate limiting, observability, conditional fallback) before chaining them.
- Direct cache control: you want to manage the PSR-16 cache key strategy yourself.
- Custom HTTP layer: you need an HTTP middleware stack the Swap builder does not expose.
If none of these apply, use Swap.
Exchanger requires PHP 8.2 or newer.
composer require florianv/exchanger symfony/http-client nyholm/psr7Any PSR-18 client paired with a PSR-17 request factory works; php-http/discovery finds them automatically.
use Exchanger\Exchanger;
use Exchanger\ExchangeRateQueryBuilder;
use Exchanger\Service\EuropeanCentralBank;
// The European Central Bank is free, no API key required.
$service = new EuropeanCentralBank();
$exchanger = new Exchanger($service);
// EUR β USD exchange rate
$query = (new ExchangeRateQueryBuilder('EUR/USD'))->build();
$rate = $exchanger->getExchangeRate($query);
$rate->getValue(); // e.g. 1.0823 (a float)
$rate->getDate()->format('Y-m-d'); // e.g. 2026-04-29
$rate->getProviderName(); // 'european_central_bank'
// Convert an amount using the returned rate
$amountInEUR = 100.00;
$amountInUSD = $amountInEUR * $rate->getValue();
// Historical rate
$query = (new ExchangeRateQueryBuilder('EUR/USD'))
->setDate((new \DateTime())->modify('-15 days'))
->build();
$rate = $exchanger->getExchangeRate($query);Exchanger retrieves the rate; your application multiplies the amount by $rate->getValue() to perform the conversion.
Wrap multiple services in a Chain to fall back when one of them errors:
use Exchanger\Exchanger;
use Exchanger\Service\Chain;
use Exchanger\Service\EuropeanCentralBank;
$service = new Chain([
new YourPrimaryService(null, null, ['api_key' => 'YOUR_KEY']),
new YourFallbackService(null, null, ['api_key' => 'YOUR_KEY']),
new EuropeanCentralBank(), // free fallback for EUR-base pairs
]);
$exchanger = new Exchanger($service);Services are tried in order. If a service does not support the requested currency pair, it is skipped silently. If a service throws an exception, the exception is collected and the next service is tried. If every service was skipped or threw, the chain raises an Exchanger\Exception\ChainException containing all collected exceptions.
- Build your own currency conversion facade on top of the provider layer.
- Integrate Exchanger into a framework that does not yet have a Swap binding.
- Wrap services with custom middleware (rate limiting, observability, request signing) before chaining.
- Power internal FX dashboards with full control over the cache key strategy.
- Implement custom HTTP layers (signed requests, mTLS, custom retries) on top of any PSR-18 client.
The Swap ecosystem is a layered toolkit for currency conversion in PHP:
- Swap. The easy-to-use, high-level API. Most apps need only Swap.
- Exchanger. The lower-level, more granular layer Swap is built on (this package). Reach for it when you need finer control over chain composition, caching, or HTTP plumbing.
- Laravel Swap. Laravel application of Swap.
- Symfony Swap. Symfony integration of Swap.
All four packages are MIT-licensed and require PHP 8.2 or newer.
Exchanger ships 30 exchange rate provider implementations. Each is registered in Exchanger\Service\Registry under the identifier shown in the table.
| Service | Identifier | Base | Quote | Historical |
|---|---|---|---|---|
| Bulgarian National Bank | bulgarian_national_bank |
* | BGN | Yes |
| Central Bank of the Czech Republic | central_bank_of_czech_republic |
* | CZK | Yes |
| Central Bank of the Republic of Turkey | central_bank_of_republic_turkey |
* | TRY | Yes |
| Central Bank of the Republic of Uzbekistan | central_bank_of_republic_uzbekistan |
* | UZS | Yes |
| Cryptonator | cryptonator |
* (crypto) | * (crypto) | No |
| European Central Bank | european_central_bank |
EUR | * | Yes |
| exchangerate.host | exchangeratehost |
* | * | Yes |
| National Bank of Georgia | national_bank_of_georgia |
* | GEL | Yes |
| National Bank of Romania | national_bank_of_romania |
(limited list) | (limited list) | Yes |
| National Bank of the Republic of Belarus | national_bank_of_republic_belarus |
* | BYN | Yes |
| National Bank of Ukraine | national_bank_of_ukraine |
* | UAH | Yes |
| Russian Central Bank | russian_central_bank |
* | RUB | Yes |
| WebserviceX | webservicex |
* | * | No |
| Service | Identifier | Base | Quote | Historical |
|---|---|---|---|---|
| AbstractAPI | abstract_api |
* | * | Yes |
| coinlayer | coin_layer |
* (crypto) | * | Yes |
| Currency Converter API | currency_converter |
* | * | Yes |
| Currency Data (APILayer) | apilayer_currency_data |
USD (free), * (paid) | * | Yes |
| CurrencyDataFeed | currency_data_feed |
* | * | No |
| currencylayer (direct) | currency_layer |
USD (free), * (paid) | * | Yes |
| Exchange Rates Data (APILayer) | apilayer_exchange_rates_data |
USD (free), * (paid) | * | Yes |
| exchangeratesapi (direct) | exchange_rates_api |
USD (free), * (paid) | * | Yes |
| fastFOREX.io | fastforex |
USD (free), * (paid) | * | No |
| Fixer (APILayer) | apilayer_fixer |
EUR (free), * (paid) | * | Yes |
| Fixer (direct) | fixer |
EUR (free), * (paid) | * | Yes |
| 1Forge | forge |
* | * | No |
| Open Exchange Rates | open_exchange_rates |
USD (free), * (paid) | * | Yes |
| xChangeApi.com | xchangeapi |
* | * | Yes |
| Xignite | xignite |
* | * | Yes |
You can also add your own provider by implementing the Exchanger\Contract\ExchangeRateService interface (see the documentation).
- Caching: PSR-16
SimpleCacheis passed as the second constructor argument:new Exchanger($service, $cache). Per-query disable:->addOption('cache', false). Per-query TTL:->addOption('cache_ttl', 3600). - HTTP client: any PSR-18 client (
symfony/http-client,php-http/guzzle7-adapter, etc.). Pass it explicitly to each service constructor, or rely onphp-http/discoveryto auto-discover. - Errors: when every service in a
Chainhas either skipped (unsupported pair) or thrown, the chain raises anExchanger\Exception\ChainExceptioncontaining all collected exceptions.
The full documentation, with the per-provider configuration reference, caching options, and how to write your own service, is in doc/readme.md.
The Swap ecosystem:
- Swap: easy-to-use PHP currency conversion library.
- Exchanger: exchange rate provider layer (this package).
- Laravel Swap: Laravel application of Swap.
- Symfony Swap: Symfony integration of Swap.
The Swap ecosystem is open to selected sponsorships from exchange rate API providers and financial infrastructure companies.
Sponsorship can include:
- Documentation visibility
- Integration examples
- Ecosystem-level visibility across Swap, Exchanger, Laravel Swap, and Symfony Swap
For inquiries, contact the maintainer via GitHub.
Issues and pull requests are welcome. Please see the existing issues before opening a new one.
The MIT License (MIT). Please see LICENSE for more information.