
stioFCS Chart is a vanilla JavaScript financial charting library for interactive Forex, cryptocurrency, and stock market charts.
It includes nine chart types, technical indicators, drawing tools, and historical replay for web-based market analysis.
It loads historical candles through FCS API and can stream live price updates through WebSocket. Historical data limits and WebSocket access depend on FCS API credentials.
Features
- Candlestick, OHLC, line, area, Heikin-Ashi, Renko, and other financial chart views.
- Over 60 technical indicators, including RSI, MACD, moving averages, and Bollinger Bands.
- Trendlines, Fibonacci tools, patterns, shapes, and text annotations.
- Up to four charts in a shared layout, with separate symbols and timeframes.
- Historical replay and screenshot export.
- Dark and light themes, chart-only display, and configurable toolbars.
- Symbol search filters for markets, exchanges, and individual assets.
- Programmatic price lines, trade markers, and configurable broker ask/bid quotes.
- Chart settings, templates, and drawing undo/redo controls.
How To Use It
Installation
Load the stylesheet and core JavaScript from a CDN:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.css"> <script src="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.js"></script>
Basic Usage
Create two nested elements and set a height on the outer container. This example uses the free chart with no API key, which limits history to 300 candles and displays provider branding.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bitcoin Price Chart</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.css">
<style>
#fcs_chartparent { width: 100%; height: 520px; }
</style>
</head>
<body>
<div id="fcs_chartparent">
<div id="fcs_chart"></div>
</div>
<script src="https://cdn.jsdelivr.net/gh/fcsapi/chart-js/src/fcsapi-chart.js"></script>
<script>
const chart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
symbol: 'BINANCE:BTCUSDT',
period: '1H',
theme: 'dark',
enableCache: false
});
</script>
</body>
</html>
Authenticate Market Data Requests
The free chart needs no credentials. For a deployed application, use an FCS API credential that matches your account and domain policy.
A domain-restricted publicKey is suitable for browser use when you configure Allowed Domains in the FCS API dashboard.
Use this initializer in place of the one in Basic Usage. Keep the HTML containers, stylesheet and script from that example.
const chart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
publicKey: 'YOUR_PUBLIC_KEY',
symbol: 'BINANCE:BTCUSDT',
period: '1H',
enableCache: false
});
The core constructor accepts four authentication configurations: an accessKey alone, a domain-restricted publicKey alone, both keys together, or a jwt_token alone. Supplying both keys hides the access key from network requests, not from page source. A server-issued JWT keeps the access key on your server and expires after a configured interval.
For JWT authentication, implement /api/chart-jwt on your own server. Its server-side request to https://api-v4.fcsapi.com/forex/jwt_token must include your private access_key and an expiry in seconds; the optional domain parameter can restrict the token to your site. Return the FCS response with status, response.jwt_token and response.expires_in to the browser. Never expose that upstream URL with your private access key in client-side code.
The following replaces the Basic Usage initializer. It obtains the first token before creating the chart and renews it for subsequent data requests. Call the returned dispose() when removing the chart.
async function mountSecureChart() {
async function getToken() {
const response = await fetch('/api/chart-jwt', {
credentials: 'same-origin'
});
if (!response.ok) throw new Error('Token endpoint failed');
const result = await response.json();
const token = result.response?.jwt_token;
const expiresIn = Number(result.response?.expires_in);
if (!result.status || !token || !(expiresIn > 0)) {
throw new Error(result.msg || 'Invalid token response');
}
return { token, expiresIn };
}
const first = await getToken();
const chart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
jwt_token: first.token,
symbol: 'BINANCE:BTCUSDT',
enableCache: false
});
let timerId;
let disposed = false;
function schedule(seconds) {
timerId = setTimeout(renew, Math.max(10, seconds - 30) * 1000);
}
async function renew() {
try {
const next = await getToken();
if (disposed) return;
chart.updateJWTtoken(next.token);
schedule(next.expiresIn);
} catch (error) {
console.error('Chart token refresh failed:', error);
if (!disposed) timerId = setTimeout(renew, 10000);
}
}
schedule(first.expiresIn);
return {
chart,
dispose() {
disposed = true;
clearTimeout(timerId);
chart.destroy();
}
};
}
mountSecureChart().catch(console.error);
Enable Live Market Updates
WebSocket updates require streaming access in addition to historical market data access. Supply your socketApiKey and keep enableSocket: true. This initializer uses a domain-restricted public key for the historical API; configure the keys for your FCS API account before using it.
const chart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
publicKey: 'YOUR_PUBLIC_KEY',
socketApiKey: 'YOUR_SOCKET_KEY',
enableSocket: true,
symbol: 'BINANCE:BTCUSDT',
period: '1m',
enableCache: false
});
Display a Compact Chart
displayMode: 'chartonly' hides the chart controls for article embeds and small market widgets.
const compactChart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
symbol: 'NASDAQ:AAPL',
period: '1D',
displayMode: 'chartonly',
enableCache: false
});
Limit Symbol Search
Restrict the symbol picker to the exchanges and assets available in your application.
const chart = new FCSAPIChart({
container: document.getElementById('fcs_chart'),
parentid: 'fcs_chartparent',
symbol: 'BINANCE:BTCUSDT',
enableCache: false,
searchModalTabs: { fav: 'Favorites', crypto: 'Crypto' },
searchAllowSymbols: ['BINANCE:BTCUSDT', 'BINANCE:ETHUSDT'],
searchExcludeSymbols: ['BINANCE:DOGEUSDT'],
searchAllowExchanges: { crypto: ['BINANCE'] },
hideExchangeInOHLC: true
});
Display Indicators and Trade Markers
Use the chart instance from Basic Usage after its initial data has loaded. Place the button before the closing </body> tag, and add the event listener after chart initialization. addIndicator() returns a Promise resolving to an indicator ID or null for an unknown type.
<button id="add-rsi" type="button">Add RSI</button>
document.getElementById('add-rsi').addEventListener('click', async () => {
const indicatorId = await chart.addIndicator({
type: 'Rsi',
length: 14
});
console.log('Indicator ID:', indicatorId);
});
Trade markers use a timestamp in Unix seconds (or a candle index) and a price from the loaded series. Substitute the correct candle timestamp and price for your data.
chart.addMarker({
timestamp: 1791388800,
price: 85200,
type: 'buy',
text: 'Entry',
id: 'trade-entry-1'
});
Set Broker Price Lines and Spreads
Horizontal lines can mark take-profit, stop-loss, and entry levels. addHorizontalLine() returns a Promise resolving to the line ID. Use prices within the range of the symbol you are displaying.
async function addTradeLevels() {
const takeProfitId = await chart.addHorizontalLine({
price: 46000,
label: 'Take Profit',
color: '#16a34a',
style: 'dashed'
});
chart.updateHorizontalLine(takeProfitId, { price: 47000 });
return takeProfitId;
}
A broker spread changes the displayed ask and bid lines, not the underlying candles. For spreadPips, the value applies to each side of the quote. A value of 10 produces a total gap of 20 pips around a close-price base.
chart.setAskBid({
base: 'close',
spreadPips: 10,
perSymbol: {
'BINANCE:BTCUSDT': { spreadPips: 15 }
}
});
// Restore the raw market quote.
chart.setAskBid(null);
Configuration Options
Containers, Data, and Authentication
| Option | Description |
|---|---|
container | Required. Inner chart DOM element. |
parentid | Required. ID of the outer chart container. |
accessKey | Private REST API key; browser code exposes it in the page source. |
publicKey | Public key restricted through Allowed Domains; it can be used alone or alongside accessKey. |
jwt_token | Short-lived FCS API JWT used alone, refreshed with updateJWTtoken() before expiry. |
socketApiKey | Separate WebSocket API key for live market updates. |
socketUrl | Custom WebSocket endpoint URL. |
url_params | Extra key-value query parameters sent with API requests; cannot replace authentication or reserved chart parameters. |
symbol | Initial EXCHANGE:SYMBOL; default BINANCE:BTCUSDT. |
period | Initial timeframe; default 1D. |
length | Requested number of candles; default 600, subject to plan limits (free chart: 300). |
enableCache | Saves recent chart preferences in localStorage; default true. |
changeURL | Updates the page URL with the chart’s symbol/period; default false. |
enableSocket | Enables live price updates when a Socket Key is available; default true. |
Appearance and Layout
| Option | Description |
|---|---|
displayMode | normal (default) for full controls, or chartonly for an embed. |
theme | light (default) or dark. |
defaultChartType | Initial chart type; default candlestick. See chart types below. |
timezone | local (default), UTC, or an offset such as +05:00. |
enableSidebar | Drawing-tool sidebar; default true. |
enableToolbar | Top toolbar; default true. |
enableRangeSelector | Bottom range selector; default true. |
enableSearch | Symbol search control; default true. |
enableIndicators | Indicator selection control; default true. |
enableMultiChart | Multi-chart layout selector; default true. |
enableReplay | Historical replay control; default true. |
enableCapture | Screenshot/export control; default true. |
enableUndoRedo | Drawing undo and redo buttons; default true. |
enableTemplates | Chart template save/load controls; default true. |
enableSettings | Chart settings control; default true. |
enableSymbolInfo | Symbol information panel; default true. |
enableChartTypeSelector | Chart type selector; default true. |
enableTimeframeSelector | Timeframe selector; default true. |
Search and Market Labels
| Option | Description |
|---|---|
searchModalTabs | Object mapping visible tab keys to labels; default null (all categories). |
searchAllowSymbols | Array of allowed symbol IDs; default null (unrestricted). |
searchExcludeSymbols | Array of blocked symbol IDs; default null. |
searchAllowExchanges | Exchange restrictions by market tab; default null. |
hideExchangeAllPlaces | Hides exchange names throughout search and chart information; default false. |
hideExchangeInOHLC | Hides exchange names only from the OHLC legend; default false. |
Search tab keys: fav, all, forex, crypto, commodity, stock, dr, fund, futures, indices, dex. For searchAllowExchanges, exchange-based tabs such as crypto, forex, and dex accept arrays. Country-based tabs such as stock, fund, dr, and indices accept objects like { US: ['NASDAQ'], PK: '*' }.
Chart Controls and Drawing
| Option | Description |
|---|---|
enableContextMenu | Chart right-click menu; default true. |
enableDrawingTools | Drawing and annotation tools; default true. |
enableGrid | Background grid; default true. |
enableCrosshair | Hover crosshair; default true. |
enableCrosshairLabels | Price/time labels on crosshair axes; default true. |
enablePriceLine | Latest-price line and label; default true. |
enableCountdown | Countdown under the latest-price label; default true. |
enableAskBidLines | Ask/bid lines; default false. A live feed requires WebSocket access. |
enableAskPriceLabels | Ask labels on the price axis; default true. |
enableBidPriceLabels | Bid labels on the price axis; default true. |
enableHighLowLabels | High/low labels for the visible data; default true. |
enableIndicatorLabels | Indicator names on chart panels; default true. |
enableOHLCBar | OHLC legend; default true. |
indicatorPanelBgColor | Indicator-panel background; default null (theme color). |
autoScale | Fits the vertical price scale to visible data; default true. |
logScale | Logarithmic price scale; default false. |
defaultMagnetMode | Snaps drawing points to candle OHLC values; default false. |
askBid | Spread and markup configuration; default null (raw quote). |
askLabelColor | Custom ask-price label color (hex value). |
bidLabelColor | Custom bid-price label color (hex value). |
lastPriceLabelColor | Latest-price label color; null uses the candle color. |
`askBid` Fields
The option accepts a spread/markup object. It only changes the quote lines and labels. Direct price-unit fields take precedence over pips, which take precedence over percent when several units are supplied for one adjustment.
| Field | Description |
|---|---|
base | feed (default) uses market ask/bid; close uses the candle close; raw disables adjustment. |
spreadPips | Adds/subtracts pips per side; default 0. |
spreadPercent | Fraction of the price per side; default 0 (0.01 means 1%). |
spread | Absolute price adjustment per side; default 0. |
markupPips | Shifts both sides by the given pips; default 0. |
markupPercent | Price-fraction markup applied to both sides; default 0. |
markup | Absolute-price markup applied to both sides; default 0. |
perSymbol | Overrides top-level rules for individual EXCHANGE:SYMBOL IDs; default {}. |
Symbol Formats
| Market | Example |
|---|---|
| Forex | FX:EURUSD |
| Cryptocurrency | BINANCE:BTCUSDT |
| Stocks | NASDAQ:AAPL |
Supported Chart Types
| Value | Display |
|---|---|
candlestick | Standard candlestick bodies and wicks. |
bars | Open-high-low-close bars. |
line | Close-price line. |
area | Filled area beneath a line. |
hollow | Hollow candles. |
heikin-ashi | Averaged Heikin-Ashi candles. |
high-low | High/low price ranges. |
volume-candles | Candles with volume-based widths. |
renko | Price-movement bricks. |
Supported Timeframes
| Category | Values |
|---|---|
| Minutes | 1m, 2m, 3m, 5m, 10m, 15m, 30m |
| Hours | 1H, 2H, 4H, 6H, 8H, 12H |
| Daily / longer | 1D, 1W, 1M |
API Methods
// Markets, timeframe, and appearance.
chart.setSymbol('NASDAQ:AAPL'); // Display another symbol.
chart.setPeriod('4H'); // Switch to a four-hour period.
chart.setTheme('light'); // Change dark/light theme.
chart.setChartType('line'); // Change chart representation.
// Quotes, indicators, and markers.
chart.setAskBid({ base: 'close', spreadPips: 10 }); // Change ask/bid rule; null resets it.
const indicatorId = await chart.addIndicator({ type: 'Sma', len: 20 }); // Promise: indicator ID or null.
chart.removeIndicator(indicatorId); // Remove an indicator by ID.
chart.addMarker({ timestamp: 1791388800, price: 85200, type: 'buy', id: 'buy-1' }); // Mark a candle.
chart.removeMarker('buy-1'); // Remove marker by ID or list position.
chart.clearMarkers(); // Remove all trade markers.
// Programmatic horizontal lines.
const lineId = await chart.addHorizontalLine({ price: 45000, label: 'TP' }); // Promise: line ID.
chart.updateHorizontalLine(lineId, { price: 46000 }); // Change one line's properties.
chart.removeHorizontalLine(lineId); // Remove one line by ID.
const lines = chart.getHorizontalLines(); // Array of programmatic lines.
const removedCount = chart.clearHorizontalLines(); // Number of removed lines.
// Export, authentication, and lifecycle.
const pngDataUrl = chart.exportImage(); // Base64 PNG data URL for image/download.
chart.updateJWTtoken('FRESH_JWT'); // Replace an expiring JWT.
chart.resize(); // Recalculate dimensions after a size change.
chart.destroy(); // Release DOM, listeners, socket, and other resources.
Indicator Input Examples
addIndicator({ type, ...inputs }) accepts a type and that study’s parameter names.
| Indicator | Input properties |
|---|---|
Sma | len, outColor |
Ema | length1, length2, length3 |
Rsi | length |
Bb | length, mult |
Macd | fast_length, slow_length, signal_length |
Marker Fields
addMarker() accepts an object describing a marker on a candle.
| Field | Description |
|---|---|
timestamp | Candle Unix timestamp in seconds, or a candle index. |
price | Price at which to place the marker. |
type | Marker style, such as buy, sell, long, short, entry, exit, tp, sl, arrow-up, arrow-down, star, or flag. |
color | Marker color. |
text | Marker label. |
id | Identifier for later removal. |
Horizontal Line Options
addHorizontalLine(options) returns a Promise for the ID. updateHorizontalLine(id, options) changes existing line properties.
| Option | Description |
|---|---|
price | Required numeric line price. |
color | Hex color; default #ff6d00. |
label | Text next to the line; default empty string. |
style | solid (default) or dashed. |
lineWidth | Line width in pixels; default 2. |
textPosition | above-left, above-center (default), above-right, below-left, below-center, or below-right. |
textColor | Label color; default #ffffff. |
textSize | Label font size; default 12. |
id | Optional custom identifier; generated automatically when omitted. |
Alternatives
- Lightweight Financial Chart JavaScript Library – lightweight-charts v5
- Intuitive Charting Library for Financial Data – DXCharts Lite
- Candlestick Chart With Technical Indicators – DojiChart







