Historical Candles
Query historical stock prices for listed, OTC, and emerging (ESB) stocks by symbol. A single query range is limited to 1 year; daily data for individual stocks goes back to 2010, index data goes back to 2015, and emerging stock data goes back to 2024.
historical/candles/{symbol}
Parameters
| Name | Type | Description |
|---|---|---|
symbol* | string | Stock Number |
from | string | Start Date (Format: yyyy-MM-dd), defaults to 1 month ago if omitted |
to | string | End Date (Format: yyyy-MM-dd), defaults to today if omitted |
timeframe | string | KLine Timeframe, defaults to D (day) if omitted; offer 1 1m; 3 3m; 5 5m; 10 10m; 15 15m; 30 30m; 60 60m; D day; W week; M month |
adjusted | string | Adjusted stock price, offer true, false (only applicable to day / week / month K) (Available >= v2.2.8) |
fields | string | Field selection, offer open, high, low, close, volume, average, turnover, change (see the Response table below for applicable timeframes) |
sort | string | Sorting, default desc descent, also offer asc ascent |
info
- Daily data update time is tentatively set to 15:30 on each trading day.
- A single query range (
from~to) is limited to 1 year. Exceeding this returns 400 Bad Request (error message:Date range must be less than one year). - Minute-level historical data is available from 2023-05-23 onward. If the query range falls entirely before this start date, or contains no trading days at all, the API returns 404 Resource Not Found (instead of an empty array).
- Emerging stock (ESB) historical data goes back to 2024 (the actual starting point varies by symbol).
Response
| Name | Type | Description | Applicable Timeframe |
|---|---|---|---|
type* | string | Security Type | — |
exchange* | string | Exchange | — |
market* | string | Market Type | — |
symbol* | string | Stock Number | — |
timeframe* | string | KLine Timeframe | — |
data* | object[] | KLine Data | — |
data.date* | string | Date (yyyy-MM-dd for day / week / month K; ISO 8601 with timezone for minute K, e.g. 2026-07-09T13:30:00.000+08:00) | All |
data.open | number | Opening Price | All |
data.high | number | Highest Price | All |
data.low | number | Lowest Price | All |
data.close | number | Close Price | All |
data.volume | number | Volume / Value, see the unit note below | All |
data.average | number | Average Price (cumulative from market open) | Minute K only |
data.turnover | number | Turnover (in NTD) | Day / Week / Month K only |
data.change | number | Price Change | Day / Week / Month K only |
caution
The unit of volume differs by symbol type and timeframe:
- Common stocks: sheets on minute K, shares on day / week / month K (1 sheet = 1,000 shares).
- Emerging (ESB) stocks: shares on both minute K and day / week / month K.
- Indices: value on minute K, shares on day / week / month K.
Examples
Day K Example
Query day K with a specified date range:
- Python
- Node.js
- C#
from fubon_neo.sdk import FubonSDK, Order
sdk = FubonSDK()
accounts = sdk.login("Your ID", "Your password", "Your cert path", "Your cert password") # Login first before connecting market-data
sdk.init_realtime() # Establish market-data
reststock = sdk.marketdata.rest_client.stock
# reststock.historical.candles(**{"symbol": "0050", "from": "2026-06-01", "to": "2026-06-05"}) # Version 2.2.3 and before
## After version 2.2.4 (use Exception for exception handling)
from fubon_neo.fugle_marketdata.rest.base_rest import FugleAPIError
try:
reststock.historical.candles(**{"symbol": "0050", "from": "2026-06-01", "to": "2026-06-05", "fields": "open,high,low,close,volume,turnover,change"})
except FugleAPIError as e:
print(f"Error: {e}")
print("------------")
print(f"Status Code: {e.status_code}") # Ex: 429
print(f"Response Text: {e.response_text}") # Ex: {"statusCode":429,"message":"Rate limit exceeded"}
const { FubonSDK } = require('fubon-neo');
const sdk = new FubonSDK();
const accounts = sdk.login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.initRealtime(); // Establish market-data
const client = sdk.marketdata.restClient
client.stock.historical.candles({ symbol: '0050', from: '2026-06-01', to: '2026-06-05', fields: 'open,high,low,close,volume,turnover,change' })
.then(data => console.log(data));
using FubonNeo.Sdk;
using FugleMarketData.QueryModels.Stock.History; //import HistoryTimeFrame
using FugleMarketData.QueryModels; //import FieldsType
var sdk = new FubonSDK();
var result = sdk.Login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.InitRealtime(); // Establish market-data
var rest = sdk.MarketData.RestClient.Stock;
var candle = await rest.History.Candles("0050", new(new DateTime(2026,6,1), new DateTime(2026,6,5), HistoryTimeFrame.Day, FieldsType.Volume|FieldsType.Change));
var candle_con = candle.Content.ReadAsStringAsync().Result;
Console.WriteLine(candle_con);
Response Body:
{
"symbol": "0050",
"type": "EQUITY",
"exchange": "TWSE",
"market": "TSE",
"timeframe": "D",
"data": [
{
"date": "2026-06-05",
"open": 105,
"high": 105.35,
"low": 102.8,
"close": 104.15,
"volume": 337031371,
"turnover": 34914259576,
"change": -1.95
},
{
"date": "2026-06-04",
"open": 106.75,
"high": 107,
"low": 106.05,
"close": 106.1,
"volume": 236782252,
"turnover": 25181889523,
"change": -1.5
},
{
"date": "2026-06-03",
"open": 107.3,
"high": 107.85,
"low": 107.1,
"close": 107.6,
"volume": 79592362,
"turnover": 8559208311,
"change": 1.9
}
]
}
Minute K Example
Query 1-minute K with a specified date range (including average price average):
- Python
- Node.js
- C#
from fubon_neo.sdk import FubonSDK, Order
sdk = FubonSDK()
accounts = sdk.login("Your ID", "Your password", "Your cert path", "Your cert password") # Login first before connecting market-data
sdk.init_realtime() # Establish market-data
reststock = sdk.marketdata.rest_client.stock
## After version 2.2.4 (use Exception for exception handling)
from fubon_neo.fugle_marketdata.rest.base_rest import FugleAPIError
try:
reststock.historical.candles(**{"symbol": "2330", "from": "2026-07-09", "to": "2026-07-09", "timeframe": "1", "fields": "open,high,low,close,volume,average"})
except FugleAPIError as e:
print(f"Error: {e}")
print("------------")
print(f"Status Code: {e.status_code}") # Ex: 429
print(f"Response Text: {e.response_text}") # Ex: {"statusCode":429,"message":"Rate limit exceeded"}
const { FubonSDK } = require('fubon-neo');
const sdk = new FubonSDK();
const accounts = sdk.login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.initRealtime(); // Establish market-data
const client = sdk.marketdata.restClient
client.stock.historical.candles({ symbol: '2330', from: '2026-07-09', to: '2026-07-09', timeframe: '1', fields: 'open,high,low,close,volume,average' })
.then(data => console.log(data));
using FubonNeo.Sdk;
using FugleMarketData.QueryModels.Stock.History; //import HistoryTimeFrame
using FugleMarketData.QueryModels; //import FieldsType
var sdk = new FubonSDK();
var result = sdk.Login("Your ID", "Your Password", "Your Cert Path", "Your Cert Password");
sdk.InitRealtime(); // Establish market-data
var rest = sdk.MarketData.RestClient.Stock;
var candle = await rest.History.Candles("2330", new(new DateTime(2026,7,9), new DateTime(2026,7,9), HistoryTimeFrame.OneMin));
var candle_con = candle.Content.ReadAsStringAsync().Result;
Console.WriteLine(candle_con);
Response Body:
{
"symbol": "2330",
"type": "EQUITY",
"exchange": "TWSE",
"market": "TSE",
"timeframe": "1",
"data": [
{
"date": "2026-07-09T13:30:00.000+08:00",
"open": 2415,
"high": 2415,
"low": 2415,
"close": 2415,
"volume": 6261,
"average": 2433.85
},
{
"date": "2026-07-09T13:24:00.000+08:00",
"open": 2430,
"high": 2435,
"low": 2430,
"close": 2435,
"volume": 114,
"average": 2439.56
},
{
"date": "2026-07-09T13:23:00.000+08:00",
"open": 2435,
"high": 2440,
"low": 2430,
"close": 2430,
"volume": 262,
"average": 2439.6
}
]
}
info
'*' Indicates mandatory disclosure fields.