How to use it: 3 steps
- Make a free Apify accountApify is the cloud platform where our tools run. The free plan gives you $5 of usage every month, no credit card needed. You pay Apify, not us.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
ktbin Banks and exchangers. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
Get today's Thai baht (THB) exchange rates from 13 Thai banks and 2 Bangkok money exchangers (SuperRich, Twelve Victory) in one table: cash buy and sell for each banknote size, transfer (T/T) and sight-bill rates, the best cash rate per currency and the bank's own update time.
Good for
- Find the bank or exchanger that pays the most THB for your USD, EUR or CNY cash today.
- Track bank buy/sell spreads for a currency during the day (ttb, CIMB Thai, LH Bank and Thai Credit Bank publish several rounds).
- Put current Thai bank rates into a spreadsheet, a travel or remittance app, or a daily report.
Who uses it
Travelers
Find who pays the most baht for your USD, EUR or CNY cash.
Remittance and travel apps
Put current Thai bank rates into a sheet or app.
Finance teams
Track buy and sell spreads during the day.
Price
Pay per event: you pay for each result the tool saves, plus a small start fee for each run. The price includes Apify platform costs. Apify bills you, not us. Prices below are for the Apify free plan.
| What you pay for | Price | When |
|---|---|---|
| Start fee | $0.00005 | Charged once per run. This tool uses 1 GB of memory or less by default; more memory costs more. |
| Rate row | $0.00005 | One saved exchange rate row: one currency at one bank or exchanger (per banknote size when quoted). Rows with status source_error, unsupported or not_quoted are free. |
Examples
- One result: about $0.0001.
- 1,000 results: about $0.05.
- Every day 100 results, for 30 days: about $0.15 a month.
Free to try: the Apify free plan gives you $5 of usage every month, no credit card needed. That is enough for about 99,000 results.
Prices checked on 8 November 2026. See the current price on Apify.
Questions
Do I need a bank account, login or API key?
No. Choose banks and currencies and start the run.
How fresh are the rates?
They are the latest rates on each provider's board at the time of the run. The updatedAt field shows the provider's update time.
Are these the rates at the branch counter?
No. These are the published board rates. A branch can offer a different rate.
What do I get on weekends and holidays?
Thai banks publish no new rates then. Each row carries the provider's last working day rates with that day in rateDate and freshness: last_trading_day, and the note says so. On a working day freshness is today. Some providers publish their first rates of the day after 8:30, so an early run can also show last_trading_day.
Why is the mid rate different from the Bank of Thailand rate?
mid is the provider's own middle rate: the average of its transfer buy and sell rates, or of its cash rates when it has no transfer pair. The Bank of Thailand publishes a separate average of all banks.
Why do I pay for a row that has only one rate?
A row is ok when the provider publishes at least one real rate for that currency. Rows without any rate are not_quoted and free.
Details
Step by step on Apify
- Open the Input tab. Banks and exchangers already has Krungthai Bank, ttb and GSB (box 1). Add or remove banks, or clear the list to read all 15 providers.
- Currencies already has
USD,EURandCNY(box 2). Clear it to get every currency. - Keep the other settings. By default you get one row per banknote size and only the latest rate round.
- Click Start at the bottom of the page.
- When the run ends, open the Output tab. Each row shows the currency, the provider, the note size, cash and transfer rates, the best-rate flags and whether the rate is from today or the last trading day.
Use cases
| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Where to sell my USD cash for the most THB today | currencies: ["USD"], all banks | one row per provider and note size | provider, denomination, buyCash, bestBuyCash | Google Sheets export |
| Compare bank transfer rates for a remittance | currencies, includeDenominations: false | one row per provider and currency | buyTransfer, sellTransfer, mid | API / webhook to your app |
| Track how a bank changes rates during the day | banks: ["ttb"], allRounds: true | one row per round | round, updatedAt, buyCash, sellCash | Apify schedule + dataset |
| Show current bank rates in a travel or money app | banks, currencies | one row per provider and currency | buyCash, sellCash, cashSpreadPct, updatedAt | API or MCP |
Tips for better results
- Pick the banks and currencies you need. A small run takes about 5 seconds.
- Run it on a schedule to build your own rate history. The Actor keeps none.
- On weekends and holidays you get the last working day's rates. Check the freshness field.
Limits and good to know
- Current rates only. No history: run the Actor on a schedule to build your own
- On weekends and holidays you get the last working day's rates (
freshness: last_trading_day); new rates come on the next working morning - These are the providers' published board rates. The rate at a branch counter can be different
kkp,eximandcitihave no readable public board (unsupportedrows)- A provider's site can be down or change its page. Then you get a
source_errorrow for it and the run isPARTIAL - Each run reads the sources for at most 240 seconds. A provider that does not answer in time gets a
source_errorrow - Some sites are slow (Kasikornbank can take 30–40 seconds), so an all-banks run can take up to about a minute
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"currency": "CNY",
"provider": "ktb",
"providerName": "Krungthai Bank",
"providerType": "bank",
"location": null,
"denomination": null,
"unit": 1,
"buyCash": 4.75,
"sellCash": 5.18,
"buyTransfer": 4.9896,
"sellTransfer": 5.1626,
"buySightBill": 4.9548,
"mid": 5.0761,
"cashSpreadPct": 8.4711,
"bestBuyCash": false,
"bestSellCash": true,
"rateDate": "2026-10-30",
"round": 4,
"updatedAt": "2026-10-30T17:08:00+07:00",
"freshness": "today",
"status": "ok",
"note": null,
"fetchedAt": "2026-10-30T14:29:48.511Z"
}Use it from code
Actor ID: cliqtomedia/thai-bank-exchange-rates-scraper. You need your Apify API token from Apify Console → Settings → API & Integrations.
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("cliqtomedia/thai-bank-exchange-rates-scraper").call(run_input={
"banks": [
"ktb",
"ttb",
"gsb"
],
"currencies": [
"USD",
"EUR",
"CNY"
]
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)curl -X POST "https://api.apify.com/v2/acts/cliqtomedia~thai-bank-exchange-rates-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"banks": ["ktb", "ttb", "gsb"], "currencies": ["USD", "EUR", "CNY"]}'# pip install langchain-apify
# set APIFY_TOKEN in your environment
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("cliqtomedia/thai-bank-exchange-rates-scraper")
result = tool.invoke({"run_input": {"banks": ["ktb", "ttb", "gsb"], "currencies": ["USD", "EUR", "CNY"]}})
print(result)The cURL call waits for the results, up to 300 seconds. For longer runs, start a run (/runs) and get the results with a webhook or by checking the run. Apify API docs. LlamaIndex, MCP for AI agents and the JavaScript client: AI agents & MCP.
Data fields (24)
| Field | Type | Meaning |
|---|---|---|
currency | string | ISO currency code, e.g. USD. * on provider-level rows (source_error, unsupported). |
provider | string | Provider code, e.g. kbank. |
providerName | string | Provider name, e.g. Kasikornbank. |
providerType | string | bank or exchanger. |
location | string | Branch or point; null = the provider's single nationwide rate. |
denomination | string | Banknote band, e.g. 50-100 for USD; null when the provider quotes one cash rate. |
unit | number | Unit the source quotes in (e.g. 100 for JPY at some banks). All rate fields are already divided to THB per 1 unit. |
buyCash | number | THB the provider pays for 1 unit of foreign banknotes. |
sellCash | number | THB the provider charges for 1 unit of foreign banknotes. |
buyTransfer | number | Buying rate for telegraphic transfers (T/T), THB per 1 unit. |
sellTransfer | number | Selling rate for transfers / drafts, THB per 1 unit. |
buySightBill | number | Buying rate for sight bills / cheques, THB per 1 unit. |
mid | number | Midpoint: transfer buy/sell average, else cash buy/sell average. |
cashSpreadPct | number | (sellCash - buyCash) / mid × 100. |
bestBuyCash | boolean | Highest cash buying rate for this currency and note size among providers in this run. |
bestSellCash | boolean | Lowest cash selling rate for this currency and note size among providers in this run. |
rateDate | string | Date of the rate board (YYYY-MM-DD, Bangkok). |
round | integer | Round number of the day, where the provider numbers them. |
updatedAt | string | Time the provider says the rates were updated (ISO 8601, +07:00). |
freshness | string | today: rates of the run's Bangkok date; last_trading_day: the provider published none today yet (weekend, holiday, early morning), so these are its latest, from rateDate. |
status | string | ok, not_quoted (listed without a rate), source_error (provider failed this run) or unsupported. |
note | string | Caveats: no cash rates at this provider, unit assumptions, error reason. |
sourceUrl | string | Page or endpoint the rates were read from. |
fetchedAt | string | When the Actor read the source (ISO 8601 UTC). |
Input settings (6)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| Banks and exchangers | banks | array | ["ktb", "ttb", "gsb"] |
| Currencies | currencies | array | ["USD", "EUR", "CNY"] |
| Separate rows per banknote size | includeDenominations | boolean | true |
| All rounds of the day | allRounds | boolean | false |
| Locations | locations | array | ["main"] |
| Proxy | proxyConfiguration | object |



