Thai Bank Exchange Rates Scraper (THB, all banks)
Pricing
from $0.05 / 1,000 rate rows
Thai Bank Exchange Rates Scraper (THB, all banks)
Compare today's Thai baht (THB) exchange rates at 13 Thai banks and the SuperRich and Twelve Victory exchangers: cash buy/sell per banknote size, transfer (T/T) rates, best-rate flags and update time. No login.
Pricing
from $0.05 / 1,000 rate rows
Rating
0.0
(0)
Developer
Cliqto Media
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Security
Limited permissionsShare
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.
Use it to compare where to buy or sell USD, EUR, CNY or other cash in Thailand, or to feed bank rates into a sheet or app. No login or API key. The smallest run (3 banks × 3 currencies) takes about 5 seconds and costs about $0.001.
Table of contents
- What it does
- How it works
- Quick start
- Use cases
- Input
- Output
- Pricing
- Limits
- API, export and integrations
- Troubleshooting
- FAQ
- Related Actors
- Support
What it does
The Actor reads the public exchange rate boards of Thai banks and exchangers at the moment you run it. It returns one row for each currency at each provider, and one row for each banknote size when the provider quotes cash by note size (for example USD 50-100, 5-20 and 1-2).
All rates are THB for 1 unit of the foreign currency. Some banks quote JPY, IDR, KRW and other currencies per 100 units; the Actor divides those, so you can compare rows directly. The field unit shows what the source used.
Providers:
| Code | Provider | Type | Cash rates |
|---|---|---|---|
bbl | Bangkok Bank | bank | yes |
kbank | Kasikornbank | bank | yes |
ktb | Krungthai Bank | bank | yes |
scb | Siam Commercial Bank | bank | yes |
bay | Krungsri (Bank of Ayudhya) | bank | yes |
ttb | ttb (TMBThanachart Bank) | bank | yes |
gsb | Government Savings Bank | bank | yes |
cimb | CIMB Thai | bank | no |
uob | UOB Thailand | bank | no |
lhb | LH Bank | bank | no |
tcrb | Thai Credit Bank | bank | no |
icbc | ICBC (Thai) | bank | few currencies |
ibank | Islamic Bank of Thailand | bank | yes |
superrich | SuperRich Thailand | exchanger | yes |
twelvevictory | Twelve Victory Exchange | exchanger | yes |
kkp (Kiatnakin Phatra), exim (EXIM Thailand) and citi (Citibank) do not publish a readable current rate board. You can still request them: each gives one free row with status unsupported.
Good fit
- 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.
How it works
- The Actor reads the current rate board of each provider you chose.
- It takes the latest rate round, converts all rates to THB per 1 unit, adds the mid rate and cash spread, and marks the best cash buy and sell rate for each currency and note size.
- It saves one row per currency and note size to the Dataset, and a short run report (
RUN_SUMMARY) to the key-value store.
On weekends and Thai holidays banks publish no new rates. The Actor then returns each provider's rates from its last working day, with the real date in rateDate and freshness: last_trading_day.
If one provider fails, you still get the rates from the others, and a free row tells you which provider failed and why.
Quick start
-
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.
Expected result: about 16 rows in 5 seconds, sorted by currency, with bestBuyCash = true on the provider that pays the most THB for each currency and note size.
Use cases
| Buyer job | Input path | Output entity | Key fields | Next integration |
|---|---|---|---|---|
| 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 |
Input
Input fields
| Field | Plain name | Type | Required | Default / prefill | Allowed values | Effect | Example | Recommendation |
|---|---|---|---|---|---|---|---|---|
banks | Banks | array of strings | no | empty = all 15 working providers; form prefill ktb, ttb, gsb | codes from the provider table, any case | which providers to read | ["kbank", "superrich"] | leave empty to compare all |
currencies | Currencies | array of strings | no | empty = every currency; form prefill USD, EUR, CNY | 3- or 4-letter codes (USD, SCOT) | which currencies to keep | ["USD", "JPY"] | name only the ones you need |
includeDenominations | Rates per banknote size | boolean | no | true | true / false | on: one row per note size; off: one row per currency with the largest notes' rates | false | turn off for one simple row per currency |
allRounds | All rate rounds today | boolean | no | false | true / false | on: also earlier rounds of today | true | for intraday tracking only |
locations | Locations | array | no | ["main"] | main, all | providers publish one rate for all branches, so both give the same rates | ["main"] | keep main |
proxyConfiguration | Proxy | object | no | off | Apify Proxy or your proxy URLs | not needed | off | keep it off |
Duplicate codes are removed. Codes can be in any case or one comma-separated string ("KTB, gsb"). An unknown bank code or a code like US$ stops the run before any request with an Invalid input message.
Input examples
Small comparison (form prefill)
{"banks": ["ktb", "ttb", "gsb"],"currencies": ["USD", "EUR", "CNY"]}
Expected behavior: reads 3 banks. Expected output: about 16 rows with buyCash, sellCash, buyTransfer, bestBuyCash. Cost note: about $0.001.
All banks, one row per currency
{"currencies": ["USD"],"includeDenominations": false}
Expected behavior: reads all 15 providers. Expected output: one USD row per provider. It can take up to about a minute because some sites are slow.
Output
The Dataset has two views: rates (currency, provider, note size, cash and transfer rates, best-rate flags, update time, status, note) and all (every field).
Output fields
| Field | Meaning | Type | Can be empty? | Example / enum | Source / notes |
|---|---|---|---|---|---|
currency | currency code | string | no | USD; * on provider error rows | provider board |
provider, providerName, providerType | who quotes the rate | string | no | ktb, Krungthai Bank, bank / exchanger | |
denomination | banknote size | string | yes | 50-100; null when the provider has one cash rate | provider board |
unit | unit the source quoted in | number | no | 1, 100 | rates are already divided to 1 unit |
buyCash, sellCash | THB the provider pays / charges for 1 unit of banknotes | number | yes | 32.95 | null at CIMB Thai, UOB, LH Bank, Thai Credit Bank |
buyTransfer, sellTransfer | transfer (T/T) rates | number | yes | 33.31 | |
buySightBill | sight bill / cheque buying rate | number | yes | ||
mid | middle rate | number | yes | average of transfer buy and sell; if the provider has no transfer pair, average of cash buy and sell | |
cashSpreadPct | cash spread in % of mid | number | yes | 8.47 | |
bestBuyCash, bestSellCash | best cash rate for this currency and note size in this run | boolean | no | true | ties are all marked |
rateDate, round, updatedAt | rate board date, round of the day, provider update time | string / integer | yes | 2026-10-30, 4, 2026-10-30T17:08:00+07:00 | provider's own date and time; on weekends and holidays the last working day |
freshness | are these today's rates? | string | yes | today, last_trading_day; null on error rows and when the provider gives no date (SuperRich) | last_trading_day: the provider has no rates today yet (weekend, holiday, early morning) |
status | row status | string | no | ok, not_quoted, source_error, unsupported | |
note | caveat or error reason | string | yes | ||
sourceUrl | page the rate was read from | string | no | ||
fetchedAt | when the Actor read it | string | no | 2026-10-30T14:29:48.511Z | UTC |
Output entities and surfaces
| Situation | Where | Result shape | User action |
|---|---|---|---|
| Normal row | Dataset | status: ok, rates filled | use the rates |
| Provider lists the currency without a rate | Dataset | status: not_quoted, rates null, free | choose another provider |
| No row matches | Dataset empty, RUN_SUMMARY.status: NO_RESULTS | check currencies; a code no provider lists gives a CURRENCY_NOT_FOUND warning | |
| One provider failed | Dataset + RUN_SUMMARY.status: PARTIAL | one free source_error row with currency: * and the reason in note | run again later; other rows are valid |
| All providers failed | run fails, RUN_SUMMARY.status: ERROR | free source_error rows | run again later |
| Spending limit reached | RUN_SUMMARY.status: CAPPED, reason CHARGE_LIMIT | rows up to the limit | raise the limit |
RUN_SUMMARY (key-value store) also lists each provider's status, rate date, warnings, counts and timing.
Output example
{"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"}
This is one row from the prefill run (sourceUrl left out). A null rate means the provider does not publish that rate type.
Pricing
Pricing unit
This Actor uses pay per event. You pay:
- Rate row: $0.05 per 1,000 saved
okrows ($0.00005 a row). - Actor start: $0.00005 once per run. Apify charges the start event per GB of run memory; this Actor uses at most 512 MB, so it is always one start event.
- Apify platform usage (compute, traffic, storage) of your run, at your plan's usual rates. A small run uses about $0.0003, an all-providers run about $0.003.
The price is the same on every Apify plan.
Rows with status not_quoted, source_error and unsupported are free. A run with no matching rows, or a run where every provider fails, costs only the start fee and its platform usage.
Cost examples
| Scenario | Input scope | Rows | Price with platform usage | Stop/cap behavior |
|---|---|---|---|---|
| No matching rows | a currency no provider quotes | 0 | about $0.0004 | run ends NO_RESULTS |
| Medium | 10 rows | 10 | about $0.0009 | |
| Prefill | 3 banks × USD, EUR, CNY | 16 | about $0.0012 | |
| Large | 100 rows | 100 | about $0.006 | |
| All providers, all currencies | {} | about 390 | about $0.023 | |
| Hourly app feed, 08:00–19:00 on weekdays | {} every hour | about 390 per run | about $0.27 a day, about $6 a month |
If you set a maximum cost per run, the Actor stops saving rows when the start and row charges reach that limit and the run ends CAPPED. Platform usage is billed on top of the limit.
Limits
- 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.
API, export and integrations
- API: start the run with
POST https://api.apify.com/v2/acts/cliqtomedia~thai-bank-exchange-rates-scraper/runsand the input JSON; read rows from the run's default Dataset. - Export: download the Dataset as JSON, CSV, Excel or HTML from the Output tab or the API.
- Scheduling: create an Apify schedule (for example every morning at 9:00 Bangkok time) to collect rates every day.
- Webhooks / no-code: use Apify integrations (Make, Zapier, Google Sheets) to send new rows to your tools after each run.
Use with AI agents (MCP)
- MCP server with only this Actor:
https://mcp.apify.com?tools=cliqtomedia/thai-bank-exchange-rates-scraper - Smallest useful input:
{"banks": ["ktb", "ttb", "gsb"], "currencies": ["USD", "EUR", "CNY"]} - Key output fields:
provider(bank code),denomination(note size),buyCash(THB paid for 1 unit of cash),sellCash(THB charged for 1 unit),bestBuyCash(best rate in this run). - A small run takes about 5 seconds and costs about $0.001. All 15 providers can take up to about a minute.
Troubleshooting
A provider has a source_error row
Symptom: the run is PARTIAL and one row has currency: * and status: source_error.
Likely reason: the provider did not answer or changed its rate board. The note gives the reason code.
Action: run again later. The other providers' rows are valid. You do not pay for the error row.
No rows for my currency
Symptom: the run is NO_RESULTS, or a currency is missing.
Likely reason: no requested provider quotes that currency, or the code has a typo. RUN_SUMMARY.warnings shows CURRENCY_NOT_FOUND for a code that no answering provider lists.
Action: check the code (ISO, for example CNY, not RMB) or clear banks to ask all providers.
Cash rates are empty
Symptom: buyCash and sellCash are null.
Likely reason: CIMB Thai, UOB, LH Bank and Thai Credit Bank publish no cash rates. Other banks show some currencies without a rate (not_quoted).
Action: use the transfer rates or choose another provider.
FAQ
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 moment of the run. updatedAt shows when the provider says it updated them; banks usually update several times a day on working days.
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.
Related Actors
- Historical Exchange Rates & Currency Converter (ECB) — official ECB reference rates for past dates and currency conversion.
Support
For a bug, question or feature request, open the Issues tab of this Actor on Apify. Add the run ID, your input and the note or warning text. Never send tokens or passwords.


