Python Currency API GuidePython 汇率 API 指南

Free Exchange Rate API Python
Guide with Working Code
Python 免费汇率 API
获取并转换汇率

Use a free exchange rate API in Python to fetch currency data, convert amounts, validate responses, and build a reliable integration.

学习用 Python 调用免费汇率接口,获取实时与历史数据、转换金额、验证响应,并构建更可靠的集成。

Whiteboard workflow showing a Python app requesting free exchange rates, parsing JSON, converting currencies, and caching results 白板流程图:Python 应用请求免费汇率 API、解析 JSON、换算货币并缓存结果

Free exchange rate API Python: the practical pathPython 免费汇率 API:实用实现路径

Pick by data needs

Compare currency coverage, update frequency, historical depth, licensing, authentication, and free-tier limits.

Make a safe request

Use a timeout, call raise_for_status(), validate JSON fields, and handle unknown currency codes.

Respect freshness

Reference rates may update daily rather than in real time. Store the provider timestamp with every value.

Cache deliberately

Match cache lifetime to the source update schedule and keep a last-known-good response for resilience.

按数据需求选择

比较币种覆盖、更新频率、历史深度、许可、鉴权方式和免费额度。

安全发起请求

设置超时、检查 HTTP 状态、验证 JSON 字段并处理无效币种。

确认数据时效

参考汇率可能每日更新,并非交易级实时行情;保存时间戳与来源。

有策略地缓存

缓存时长应匹配源数据更新节奏,并保留最后一次有效结果。

How to choose a free currency exchange rate API如何选择免费的货币汇率接口

“Free” can mean an open public endpoint or a limited free plan. Before using any provider, verify whether an API key is required, how often rates refresh, which currencies and dates are available, and whether the terms permit your intended use.

“免费”可能指开放公共接口,也可能只是有限额度。接入前要核对是否需要 API Key、更新频率、币种与日期覆盖、请求配额,以及许可是否适合你的用途。

Criterion标准What to verify需要核对Why it matters重要原因
Authentication鉴权No key, free key, or paid key免 Key、免费 Key 或付费 KeyChanges setup and secret management影响接入和密钥管理
Freshness时效Daily, hourly, or intraday每日、每小时或盘中Reference data is not a trading quote参考价不等于成交报价
Coverage覆盖Currencies, history, base selection币种、历史范围、基准币Prevents missing pairs later避免后续缺少货币对
Limits限制Quota, rate limit, attribution, license配额、限流、署名和许可Determines production suitability决定能否用于生产

Free exchange rate API without an API key无需 API Key 的免费汇率接口

A no-key endpoint is convenient for a prototype, but it still needs timeouts, caching, respectful request volume, and a fallback plan. Frankfurter documents a public, open-source API with no API key and daily central-bank-derived rates.

免 Key 接口适合原型,但仍应设置超时、缓存、合理请求频率和降级方案。Frankfurter 的官方文档说明其公共开源接口无需 API Key,并提供央行来源的日度汇率。

Public API, free tier, or paid market feed?公共 API、免费套餐还是付费行情?

Choose a public reference-rate API for prototypes, reporting, analytics, and low-frequency price localization. A registered free tier may offer broader currency coverage or more frequent updates, but introduces key rotation and quota monitoring. Trading, settlement, compliance, or customer-facing quotes may require a licensed market-data feed with explicit service levels.

公共参考汇率 API 适合原型、报表、分析和低频价格本地化。需要注册的免费套餐可能覆盖更多币种或提高更新频率,但也带来密钥轮换和配额监控。交易、结算、合规或面向客户的报价,通常需要具有明确授权和服务等级的市场数据源。

Questions to answer before integration接入前必须回答的问题

  • Does the source publish reference, mid-market, buy, sell, or executable rates?
  • Which timezone defines the response date, and how are weekends handled?
  • Can the base currency change, or must cross-rates be calculated locally?
  • Are attribution, caching, redistribution, or commercial-use restrictions present?
  • 数据是参考价、中间价、买入价、卖出价,还是可成交报价?
  • 响应日期采用哪个时区,周末和节假日如何处理?
  • 能否切换基准币,还是需要在本地计算交叉汇率?
  • 是否存在署名、缓存、再分发或商业使用限制?

Get live exchange rates in Python with requests用 requests 在 Python 中获取最新汇率

The example uses a documented single-pair endpoint. “Latest” means the provider's latest published reference rate; inspect the returned date and provider information instead of assuming tick-by-tick market data.

下面使用文档公开的单一货币对接口。“最新”指服务商最近发布的参考汇率,应检查响应日期和来源,不要把它当成逐笔实时行情。

from dataclasses import dataclass
from datetime import date
from decimal import Decimal, InvalidOperation

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry


@dataclass(frozen=True)
class RateObservation:
    observed_on: date
    base: str
    quote: str
    rate: Decimal


def build_session() -> requests.Session:
    retry = Retry(
        total=4,
        connect=3,
        read=3,
        status=3,
        backoff_factor=0.5,
        status_forcelist=(429, 500, 502, 503, 504),
        allowed_methods=frozenset({"GET"}),
        respect_retry_after_header=True,
        raise_on_status=False,
    )
    session = requests.Session()
    session.mount("https://", HTTPAdapter(max_retries=retry))
    return session


def get_rate(
    session: requests.Session,
    base: str = "USD",
    quote: str = "EUR",
) -> RateObservation:
    base, quote = base.upper(), quote.upper()
    if not (len(base) == len(quote) == 3 and base.isalpha() and quote.isalpha()):
        raise ValueError("Currency codes must contain three letters")

    url = f"https://api.frankfurter.dev/v2/rate/{base}/{quote}"
    response = session.get(url, timeout=(3.05, 10))
    response.raise_for_status()
    data = response.json()

    required = {"date", "base", "quote", "rate"}
    if not required <= data.keys():
        raise ValueError("Unexpected exchange-rate response")
    if data["base"] != base or data["quote"] != quote:
        raise ValueError("Provider returned a different currency pair")

    try:
        observed_on = date.fromisoformat(data["date"])
        value = Decimal(str(data["rate"]))
    except (TypeError, ValueError, InvalidOperation) as exc:
        raise ValueError("Invalid date or exchange rate") from exc
    if not value.is_finite() or value <= 0:
        raise ValueError("Exchange rate must be a positive finite number")

    return RateObservation(observed_on, base, quote, value)


session = build_session()
rate = get_rate(session, "USD", "EUR")
print(rate.observed_on, rate.rate)

Handle timeouts, HTTP errors, and malformed JSON处理超时、HTTP 错误和异常 JSON

Catch requests.Timeout, requests.HTTPError, and requests.JSONDecodeError separately. Log the provider, pair, status, and timestamp without exposing credentials. Retry only transient failures with backoff.

分别处理 requests.Timeoutrequests.HTTPErrorrequests.JSONDecodeError。记录服务商、货币对、状态和时间,但不要泄露密钥;只对临时故障执行退避重试。

Convert currency amounts in Python在 Python 中换算货币金额

For a single-pair response, multiply the amount by the returned rate and use Decimal with an explicit rounding rule when money is displayed or stored. Keep the original rate, timestamp, and source for auditability.

对单一货币对响应,用金额乘以返回汇率。展示或存储金额时使用 Decimal 并明确舍入规则,同时保存原始汇率、时间戳和来源,便于审计。

from decimal import Decimal, ROUND_HALF_UP

def convert_amount(amount, rate, minor_units=2):
    value = Decimal(str(amount)) * Decimal(str(rate))
    quantum = Decimal("1").scaleb(-minor_units)
    return value.quantize(quantum, rounding=ROUND_HALF_UP)

converted = convert_amount("125.50", rate.rate)
print(f"125.50 USD = {converted} EUR")

Use a session, retry only transient failures复用 Session,只重试临时故障

The shared requests.Session reuses connections. Its adapter retries connection and read failures, HTTP 429, and selected 5xx responses with bounded exponential backoff, while respect_retry_after_header=True follows server-supplied waiting guidance. Invalid currency codes and other deterministic 4xx responses are not retried. Keep attempts bounded so a dependency problem cannot consume every application worker.

共享的 requests.Session 会复用连接。适配器只对连接或读取故障、HTTP 429 和部分 5xx 响应执行有次数上限的指数退避;respect_retry_after_header=True 会遵守服务端给出的等待时间。无效币种等确定性的 4xx 错误不会重试。必须限制尝试次数,避免外部依赖故障耗尽应用工作线程。

Exchange-rate direction, cross rates, and money rounding汇率方向、交叉汇率与金额舍入

Define every rate as units of quote currency per one unit of base currency. If USD/EUR = 0.92, one U.S. dollar converts to 0.92 euros; the inverse EUR/USD is 1 / 0.92, not 0.92. Preserve the provider's stated pair and never infer direction from a field name such as rate alone.

应把每个汇率定义为“1 单位基准币可兑换多少单位目标币”。如果 USD/EUR = 0.92,表示 1 美元可兑换 0.92 欧元;反向的 EUR/USD 应为 1 ÷ 0.92,不能仍写成 0.92。必须保存供应商返回的货币对方向,不能只凭一个名为 rate 的字段猜测。

Worked example: derive a cross rate with Decimal.

Assume one source publishes USD/EUR = 0.9200 and USD/JPY = 150.00 at the same observation time. Because both use USD as the base, EUR/JPY = 150.00 / 0.9200 = 163.043478…. Converting EUR 1,250 gives JPY 203,804.347… before currency-specific rounding. The rate may be stored at higher precision, while a payable amount can be rounded separately under the application's monetary rule. Do not round each intermediate leg or mix rates from different dates.

计算示例:使用 Decimal 推导交叉汇率。

假设同一观测时点的 USD/EUR = 0.9200USD/JPY = 150.00。两组汇率都以美元为基准,因此 EUR/JPY = 150.00 ÷ 0.9200 = 163.043478…。1,250 欧元可换算为 203,804.347… 日元,再按业务规定的日元金额精度舍入。汇率可以保留更高精度,实际应付金额则按独立规则舍入;不能在每个中间步骤提前截断,也不能混用不同日期的两组汇率。

Reference is not executable

A central-bank or daily midpoint can support accounting and reporting, but it is not a guaranteed bid or ask. A payment or trading quote may also include spread, fees, timing and venue.

Observation date is not request date

A weekend request may return Friday's published rate. Store requested date, source observation date, publication time and retrieval time separately; never relabel a carried rate as a new observation.

Rounding belongs to the amount

Keep calculations in Decimal and quantize the final monetary amount using the currency and business rule. Preserve the unrounded rate and calculation trace for reconciliation.

参考汇率不等于可成交报价

央行参考价或日度中间价可用于会计与报表,但并不是保证可成交的买价或卖价。支付或交易报价还可能包含点差、费用、时点和交易场所差异。

观测日期不等于请求日期

周末发起请求时,接口可能返回周五公布的汇率。应分别保存请求日期、源观测日期、发布时间和抓取时间,不能把沿用值重新标成当天观测。

舍入应作用于最终金额

计算过程使用 Decimal,最终金额再依据币种精度和业务规则量化;同时保留未舍入汇率与计算链,方便后续对账。

Fetch historical exchange rates with Python用 Python 获取历史汇率数据

Historical endpoints commonly accept a date or date range. Validate ISO currency codes and dates before the request, then decide how weekends, holidays, missing observations, and provider revisions should be represented in your application.

历史接口通常接收日期或日期范围。请求前校验 ISO 币种代码和日期,并明确周末、节假日、缺失值及服务商修订在应用中的处理方式。

Cache rates without serving stale data silently缓存汇率但不要静默返回过期数据

Store the source date next to the value, set cache expiry from the provider's publication cadence, and surface stale status to callers. For production, monitor failures and keep a last-known-good value with a clear age.

把来源日期和汇率一起存储,按服务商发布节奏设置过期时间,并向调用方明确标记陈旧状态。生产环境应监控失败,并保留带明确年龄的最后有效值。

Build a time series without hidden gaps构建不隐藏缺口的汇率时间序列

Keep the provider date as the observation key rather than replacing it with the request time. Store missing dates explicitly or document forward-fill rules. When comparing providers, normalize base currency, timezone, decimal precision, and holiday calendars before calculating returns or averages.

应使用服务商返回的日期作为观测键,不要用请求时间替代。对缺失日期进行明确记录,或清楚说明向前填充规则。比较不同数据源前,需要统一基准币、时区、小数精度和节假日日历,再计算收益率或平均值。

Production checklist for a Python exchange rate integrationPython 汇率集成的生产检查清单

A successful HTTP 200 response is only the first check. Production code should verify schema, currency pair, source date, numeric range, cache age, and provider identity before a rate reaches pricing or reporting logic.

HTTP 200 只代表请求成功。汇率进入定价或报表逻辑前,生产代码还应验证响应结构、货币对、来源日期、数值范围、缓存年龄和服务商身份。

Validate every response

Reject missing fields, non-numeric rates, unexpected base or quote currencies, impossible values, and timestamps that move backwards.

Separate fetch from conversion

Keep network access, normalization, business conversion, rounding, and presentation in separate functions so each can be tested.

Use a typed internal rate record

Normalize provider JSON into a dataclass or validated model containing base, quote, Decimal rate, observation date, retrieval time, source, and stale status. Downstream code should not depend on a vendor's raw field names.

Observe freshness and failures

Track request latency, status classes, quota headers, cache hits, source age, retries, and fallback usage.

Design a bounded fallback

Use a circuit breaker after repeated failures and define whether callers receive a clearly aged last-known-good rate or an unavailable result. Never switch providers without recording the new source and rate semantics.

Protect credentials

Load API keys from a secret manager or environment, never source control, logs, browser code, or exception messages.

验证每一次响应

拒绝缺失字段、非数字汇率、意外的基准币或目标币、不合理数值,以及时间戳倒退的数据。

分离获取与换算逻辑

将网络请求、格式标准化、业务换算、舍入和展示拆成独立函数,便于分别测试。

建立带类型的内部汇率记录

把供应商 JSON 统一为 dataclass 或经过校验的数据模型,至少包含基准币、目标币、Decimal 汇率、观测日期、抓取时间、来源和陈旧状态。下游代码不应依赖供应商原始字段名。

监控时效与失败

记录请求延迟、状态码类别、配额响应头、缓存命中、数据年龄、重试和降级使用情况。

设计有边界的降级方案

连续失败后启用熔断,并明确调用方收到的是标有数据年龄的最后有效汇率,还是不可用结果。切换供应商时不得隐藏新的来源和汇率口径。

保护访问凭证

从密钥管理服务或环境变量读取 API Key,禁止写入源码、日志、浏览器代码或异常消息。

Test cases worth automating值得自动化的测试用例

  • Valid latest and historical responses with fixed fixtures.
  • Timeout, connection reset, 429, 500, malformed JSON, and missing fields.
  • Unsupported currency codes, same-currency conversion, zero and negative amounts.
  • Weekend dates, stale cache, provider date changes, and rounding for different minor units.
  • 使用固定样本测试最新与历史汇率的正常响应。
  • 测试超时、连接重置、429、500、异常 JSON 和缺失字段。
  • 测试不支持的币种、同币种换算、零金额和负金额。
  • 测试周末日期、陈旧缓存、服务商日期变化及不同最小货币单位的舍入。

How QVeris helps Python apps find exchange rate capabilitiesQVeris 如何帮助 Python 应用查找汇率能力

QVeris helps developers and agents discover and inspect available capabilities before calling them. Use the QVeris tool details to evaluate relevant financial-data tools, then verify each provider's documentation, terms, freshness, and limits.

QVeris 帮助开发者和 Agent 在调用前发现并检查可用能力。你可以通过 QVeris 工具详情筛选相关金融数据工具,再逐一核对服务商文档、许可、时效和限制。

  • Discover exchange-rate and currency-data capabilities by task.
  • Inspect inputs and outputs before integrating a provider.
  • Keep provider claims separate from application-level reliability checks.
  • 按任务发现汇率与货币数据能力。
  • 接入前检查输入、输出和调用要求。
  • 区分服务商声明与应用自身的可靠性验证。

Free exchange rate API Python FAQPython 免费汇率 API 常见问题

Is there a free exchange rate API for Python?

Yes. Python can call public or freemium REST APIs. Compare keys, quotas, freshness, currency coverage, history, and license before choosing.

How do I get exchange rates in Python?

Send a timed GET request, check HTTP status, parse JSON, validate its fields, and cache the response according to the source schedule.

Can I get historical exchange rates for free?

Some providers offer free historical daily rates. Date range, currencies, attribution, and quota vary, so check current documentation.

Is a free currency API real time?

Not necessarily. Many free sources publish daily reference rates. Read the timestamp and update policy instead of relying on a “live” label.

Python 有免费的汇率 API 吗?

有。Python 可以调用开放或提供免费额度的 REST API。选择前比较密钥、配额、时效、币种、历史数据和许可。

Python 如何获取实时汇率?

发送带超时的 GET 请求,检查 HTTP 状态,解析并验证 JSON,再按数据源更新周期缓存。注意“实时”可能只是最新参考价。

哪里可以免费获取历史汇率?

部分服务提供免费的历史日度汇率,但日期范围、币种、署名和配额不同,应查看当前官方文档。

免费汇率接口需要 API Key 吗?

不一定。有的公共接口免 Key,有的免费套餐需要注册。免 Key 也不代表没有合理使用或限流规则。

Authoritative references权威参考