Reference
Limits
Every number the embed enforces, in one place, read out of the code that enforces it. Most are far above anything a real integration reaches; they are here so that hitting one is a thing you can look up rather than discover.
What a URL may say
| Limit | Value | What happens past it |
|---|---|---|
| Symbol length | 32 characters | The chart draws its refusal instead. A symbol is echoed into that page, so an unbounded attacker-supplied string in a document is how a small mistake becomes a large one. |
Length of the whole live= string | 256 characters | The value is ignored and the full chart is drawn. The longest valid value is a fraction of this. |
A live chart's window | 60 to 31,622,400 seconds | Outside that range the window falls back to its default, 60 bars of the interval. |
| Bars a live chart asks for and keeps | 1000 | A window that would need more starts part-way in. It bounds both the history request and what an open page holds in memory. |
| Indicators named | 5 | The rest are dropped. Each is a fetch, a compile and a Worker in the reader's browser. |
Length of the whole indicators= string | 512 characters | The list is refused entirely rather than truncated. Five ids at their own limit plus separators is a small fraction of this, so no honest URL is near it. |
| Display currencies offered | 8 | The rest are dropped. The FIRST is the one the chart opens in. |
Session bands in sessions= | 8 | The rest are dropped. Each band is a full-plot fill per visible run on every repaint, so the list is bounded on its output like the indicators. |
| A session band's label in the URL | 32 characters | Letters, digits, spaces and _ . + & / -. A longer or stranger label costs its own band, never the rest. |
Session bands in setSessions | 16 | Wider than the URL's, because a host naming full band objects is writing code rather than a query string; past it the whole call is refused by name. |
Things you draw on the chart
| Limit | Value | What happens past it |
|---|---|---|
A loadState document, or one setDrawings call | 512,000 characters of JSON | commandError, naming the size. The caps are generous, since a chart state is a whole document, and they bound what the frame will hold rather than what the product allows. Anything larger is a defect or an attack. |
Starred timeframes in a loadState (favoriteIntervals) | 24 | commandError, naming the key, and nothing in the state is applied. More than any interval menu offers, so a list the reader built always fits. |
Drawings in one setDrawings | 500 | commandError. Each is hit-tested on every pointer move, so this bounds the reader's cursor rather than our memory. |
| Lines and markers on one chart | 200 | commandError, naming the count. Every one is drawn each frame, so this bounds the reader's frame rate rather than our memory. |
text and tooltip length | 200 characters | commandError. It is drawn on a canvas at a fixed size; a ten-thousand-character label is not a label. |
lineWidth, arrowHeight, arrowSpacing | 1 to 100 pixels | commandError. Zero and negative are not widths, and a five-figure one is painting over the reader's chart rather than drawing on it. |
Labels drawn ON a line (takeProfitLabel, addTakeProfitLabel, …) | 24 characters | commandError. The box MEASURES the label and grows to hold it, so a long one is not an ugly label, it is a pill reaching across the plot and covering the price action underneath. A line's own text is capped far higher because its body is meant to be wide. |
bodyFont, quantityFont, font | 120 characters | commandError, and so does any url(): a canvas that fetches from a page we do not control is a beacon we would be hosting, the same rule a colour follows. The string is measured on every frame a line is drawn, so the cap is a cost the reader would otherwise pay. |
Points on a createMultipointShape | 2 to 8 | commandError. Two is a trend line, three a triangle; past a handful it is not a drawing, it is a series, and a series belongs in the datafeed. |
Colours
| Limit | Value | What happens past it |
|---|---|---|
| Roles you may set | 10 | That IS the whole list, so nobody reaches it by using the feature. It bounds the work a stranger's URL can ask for: the parser stops once it has enough VALID pairs, so a string of nothing but invalid ones is walked in full. |
Length of the whole colors= string | 632 characters | The palette is dropped ENTIRELY rather than truncated, so the chart keeps the theme's own colours. Derived from the roles rather than picked: every role at its full spelling with an eight-digit value is a quarter of this. |
A value in data-colors or setStyle | #rgb · #rrggbb · #rrggbbaa | The attribute drops that pair; setStyle refuses the call by name. Nothing else is accepted, including rgb() and colour names. See Styling for why a strict grammar is a security property here. |
Buttons you add to the toolbar
| Limit | Value | What happens past it |
|---|---|---|
| Buttons on one chart | 8 | commandError. A header has finite room, and past it the displaced controls are the chart's own. |
A button's text | 32 characters | commandError. Much shorter than a line's label, because this one sits in a fixed row rather than on a canvas. |
| A chart with no toolbar | data-toolbar="1" required | commandError naming the attribute. The engine would create the button, since the header is only hidden rather than absent, so refusing the call is what prevents a control no reader can see. |
Indicators you add
| Limit | Value | What happens past it |
|---|---|---|
| Indicator name, and each string input | 64 characters | commandError. |
Inputs to one createStudy | 16 | commandError. Inputs may be numbers, short strings or booleans; nothing else is accepted. |
There is no cap on how many indicators a HOST may add, because removeAllStudies exists and the reader's frame rate is the only thing at stake. The indicators= parameter is capped because that list runs somebody else's code.
Trading
| Limit | Value | What happens past it |
|---|---|---|
setTrading unit label | 24 characters | TRUNCATED, and this is the one exception on the page. See below. |
setTrading quantity | any positive number | commandError. A declared size that is absent, zero, negative or not a number withdraws the one-click rows rather than defaulting: the rows PRINT it, and "Buy NaN" is a control whose label is untrue about an order. |
setTrading would withdraw the Buy and Sell rows over a cosmetic string. Worth knowing rather than worth changing, and it is here because a silent truncation nobody documented is exactly the kind of thing this page exists for.The frame
| Limit | Value | What happens past it |
|---|---|---|
Height in a ready or resize message | 40 to 10,000 pixels | The message is refused, not clamped. A clamp would silently accept a hostile ten-million-pixel value as a legitimate 4,000, which teaches a host nothing and leaves a wrong-looking page. |
That bound is on the MESSAGE, not on your CSS. You may size the iframe however you like; see Styling for what a chart at each size is actually like to read.
Seeing a refusal
Everything above except the frame height comes back on the same channel, so one handler catches all of them.
try {
await chart.createOrderLine({ text: 'x'.repeat(1000) });
} catch (err) {
// "text must be a string of at most 200 characters"
console.warn(err.message);
}commandError message carrying { id, reason }. The loader turns it into a rejected promise and nothing else; there is no extra information it holds back.Limits that are not here
Two kinds are deliberately absent. Rate limits are not published as a number, because the per-IP backstop in front of this app is a denial-of-service ceiling rather than a product rule and a figure would invite designing against it. And nothing here bounds YOUR datafeed: how many bars you return, how often you tick and how much history you hold are yours, and the chart asks for what it needs.
The reader's sign-in credential has its own bounds, which are a security property rather than an integration one and are described on the security model.