How to send a chart alert to a trading bot
A TradingView alert can POST to a bot that places the order. What the webhook costs, what it does not promise, and where the secret ends up.
Create a TradingView alert with a webhook URL — a paid feature from Essential up, with two-factor authentication switched on — and point it at a bot that accepts one: 3Commas or Altrady hosted, OctoBot or Gunbot on your own server, or a receiver you write around CCXT. TradingView sends one POST, cancels it after three seconds and documents no retry, so the bot has to reject stale, repeated and unauthenticated messages by itself.
The short way
TradingView does not place orders from an alert. It sends one: when an alert fires, it POSTs the message you wrote to a URL you gave it, and whatever answers that URL does the trading. So the job is three settings on the TradingView side and one bot that accepts webhooks on the other.
On the TradingView side: a paid plan, because the pricing table marks webhook notifications as
absent on Basic and present from Essential upward; two-factor authentication on the account,
because webhook alerts are refused without it; and a URL on port 80 or 443 over IPv4, the only
ports and the only protocol the help centre accepts. Then write the alert message in whatever
format the receiving bot reads — usually JSON, which TradingView sends as application/json when
it parses, and as text/plain when it does not.
On the other side, the least work is a hosted signal bot. A 3Commas signal bot gives you a URL and a message template to paste into the alert; the message carries your bot's identifiers and a secret, and TradingView's placeholders fill in the rest when it fires:
{
"secret": "YOUR_BOT_SECRET",
"max_lag": "300",
"timestamp": "{{timenow}}",
"trigger_price": "{{close}}",
"tv_exchange": "{{exchange}}",
"tv_instrument": "{{ticker}}",
"action": "enter_long",
"bot_uuid": "YOUR_BOT_UUID"
}
Two of those fields are doing more work than the rest. secret is the only thing standing between
the URL and anyone who learns it. max_lag is the largest delay you will accept between
timestamp and execution, in seconds — anything from 10 to 86,400, 300 by default — and a signal
past it is treated as invalid. It is the one field in this chain that guards against an order
placed on a price from five minutes ago. Keep both. The
rest of this page is about why.
What the options are
Hosted, JSON in. 3Commas, above, runs signal bots from the Pro plan; the free plan cannot trade
at all. Altrady is the same shape on every tier: a webhook builder generates the
JSON, which carries the api_key and api_secret from the bot's settings, and the message names the action —
open, increase, reduce, close or reverse — the exchange and the market. Both run on the vendor's
servers, so they keep working with your machine off, and both hold your exchange keys to do it.
Self-hosted, text in. OctoBot reads its own format, one KEY=VALUE per line
or separated by semicolons:
EXCHANGE={{exchange}}
SYMBOL={{ticker}}
SIGNAL=BUY
TOKEN=YOUR_OCTOBOT_TOKEN
The webhook server listens on port 9000 by default, which TradingView will not call, so the bot either opens an ngrok tunnel — built in, with your ngrok token — or sits behind a proxy you run on 443. Gunbot takes a single space-separated line, passphrase first:
YOUR_PASSPHRASE binance buy USDT-BTC 0.1 0
— exchange, side, pair, amount and a price, where 0 means a market order — and its documentation
requires the bot itself to be publicly reachable on 443. Both keep the exchange keys on your own
machine, which is the reason to choose them; the network exposure is the cost.
Your own receiver. A few dozen lines of any web framework, with CCXT behind them to place the order on whichever venue you trade. This is the only version in which every check described below is code you can read: the secret comparison, the age check, the duplicate filter, and what happens to a close that arrives when there is nothing open. It is also the only one in which all of that is your bug.
Where this breaks
The secret travels in the message body. TradingView's webhook sends the message you typed and
nothing else you control: the help page describes no custom header and no signing. So every bot on
this page authenticates the same way — a value inside the body. 3Commas calls it secret, Altrady
api_secret, OctoBot TOKEN, Gunbot a passphrase. That puts the credential in the alert
definition, in the alert log, in any screenshot of either, and in any script that builds the
message from inputs and gets shared. TradingView's own page asks you not to put "sensitive
information such as login credentials or passwords in the webhook body", which is advice no
receiver here lets you follow. What you can do is limit what the secret opens: a bot-scoped value
rather than anything reused, exchange keys with withdrawals disabled, and — if the receiver is
yours — a check that the request came from one of the four IPv4 addresses TradingView publishes.
One self-hosted bot ships with the check switched off. OctoBot generates a token when the
TradingView service is configured, but require-token defaults to false, so until you turn it
on any POST to the URL in the right format is a signal. On a URL that has been pasted into a tunnel
dashboard, a chat or a support thread, that is the whole of the security.
There is no retry, and three seconds is the deadline. TradingView cancels a request the server takes longer than three seconds to answer, says webhooks "may occasionally fail to reach the specified URL", and points you at a status column in the alert log. Nothing on the page promises a second attempt. A receiver that places the order before responding can blow the deadline on a slow exchange call; one that is restarting when the alert fires simply misses it. A missed entry costs an opportunity. A missed exit leaves a position open that the chart believes is closed — which is why Altrady recommends a single reverse signal over a close followed by an open, noting that with separate signals "the timing of the close is unknown".
The alert fires later than the bar closes. With "once per bar close", TradingView waits for the
first trade of the next bar before it can be sure the previous one has closed; on a thin market that
can be several seconds, and with no trades at all the server closes the bar itself one minute after
the formal close. Add the exchange call on the far side, and the order is priced by the market that
exists then, not by {{close}}. That is what max_lag is for; a receiver of your own should compare
{{timenow}} with its own clock and refuse old signals the same way.
A signal that repaints can trade and then vanish. The default frequency for a script's
alert() is once per bar, which fires on the first call during the live bar — before the bar is
confirmed. An indicator whose condition is true mid-bar and false at the close has sent a webhook
by then, and the chart afterwards shows no signal where your bot traded. Pine's documentation
defines repainting as historical and real-time calculations behaving differently, and says the
simplest way to avoid it in alerts is to trigger only on bar close, at the price of immediacy.
Values requested from another timeframe are the other usual cause: on real-time bars they can be
unconfirmed.
An alert runs the script as it was when you created it. TradingView saves a copy of the script, its inputs, the symbol and the timeframe; later edits "will not affect running alerts previously created from them". Fix a bug in the indicator and the bot keeps trading the buggy version until the alert is deleted and made again.
An alert that fires too often is stopped. More than 15 triggers in three minutes and TradingView halts it. A condition that flickers on a fast chart can switch off your bot's only input without anything on the bot's side noticing.
If you outgrow this
If the problem is that a missed webhook is a missed trade, stop treating the alert as the order. Make it a notification that the bot reconciles against: on each message, the receiver reads the position from the exchange and moves it toward what the signal says it should be, so the next message repairs whatever the last lost one broke. A hosted signal bot cannot be made to work this way; your own receiver can.
If the problem is that the logic lives in someone else's charting language, the durable fix is to move it next to the orders. Freqtrade, Hummingbot and OctoBot compute their signals from the exchange's own feed inside the bot process, which removes the webhook, the three-second deadline and the secret in the body at once — and brings a backtest that runs the same code, which a Pine alert never had. The costs of that are covered in what a crypto backtest silently assumes.
If the problem is that the chart is not TradingView, check the webhooks line on the card before building anything. Of the nine charting cards in this catalogue that alert at all, three list webhooks — TradingView, CoinAnk and GoCharting, where alert webhooks sit on a paid plan — and the rest notify a person rather than a program. The same caution applies at the far end: Tealstreet has a local listener but no hosted path for an alert to reach it, and Bitsgap accepts no webhooks at all. The trading bots listing is where to compare the rest.
The tools named above
In the order this page puts them in, which is an editorial judgement and not a ranking anyone paid for.
3Commas
Signal bots take a JSON body carrying the bot's secret, plus an optional max_lag that refuses a signal older than you allow. Signal bots start on Pro.
Hosted DCA, grid and signal bots over nine exchanges, with your keys on their servers.
$20/moFree tier
Altrady
A hosted signal bot on every tier, fed JSON carrying the bot's key and secret. Its test flag works on open signals only; any other signal goes live.
Multi-exchange trading workspace — smart orders, scanners, bots and a journal.
€10/moFree tier
OctoBot
Self-hosted, with its own KEY=VALUE alert format, reached through ngrok or a proxy you run — and a token check that ships switched off.
GPL-3.0 Python bot with a web interface for grid, DCA, basket and TradingView strategies.
FreeFree tierOpen source
Gunbot
A self-hosted licence that reads a space-separated alert starting with your passphrase, and must listen publicly on port 443.
A closed-source bot you install once, licensed against an ERC-20 wallet you control.
€29/mo
CCXT
Write the receiver yourself — check the secret, drop repeats, then place the order through one client. The only option where every check is yours to see.
One MIT client for 104 crypto exchanges, 76 of them over websocket.
FreeFree tierOpen source
FAQ
Do TradingView webhook alerts need a paid plan?
Yes. The plan comparison marks webhook notifications as unavailable on the free Basic plan and included from Essential upward. Separately from the plan, the account needs two-factor authentication switched on, and the receiving URL has to be on port 80 or 443 over IPv4.
Does TradingView retry a webhook that failed?
Nothing in its documentation says so. The help page says a request is cancelled if the server takes more than three seconds to answer, that webhooks may occasionally fail to reach the URL, and that delivery can be checked in the webhook status column of the alert log. Build the receiver on the assumption that a message can be lost.
How do I keep someone else from triggering my bot's webhook?
TradingView cannot add headers or sign a request, so the check has to be inside the message — the secret, token or passphrase each bot defines. Make sure it is actually enforced (OctoBot's is off by default), keep it out of shared scripts and screenshots, use exchange keys without withdrawal rights, and on a receiver you run, accept requests only from the four IPv4 addresses TradingView publishes.
Why did my bot trade on a signal that is not on the chart?
Usually because the alert fired during a live bar and the condition was no longer true when the bar closed. A script's alert() defaults to once per bar, which fires on the first qualifying tick. Setting the alert to once per bar close waits for confirmation — at the cost of firing later, sometimes seconds and occasionally a minute after the close.
Sources
- How to configure webhook alerts — TradingView, read
- Compare plans — TradingView, read
- Delays in OncePerBarClose alerts — TradingView, read
- Alert was triggered too often and stopped — TradingView, read
- Pine Script v6 User Manual — Alerts — TradingView, read
- Pine Script v6 User Manual — Repainting — TradingView, read
- Signal bot: JSON file in Custom signal type — 3Commas,
- Webhook Signal Reference: Open, Increase, Reduce, Close, and Reverse — Altrady, read
- Services/Services_bases/trading_view_service/trading_view.py — Drakkar-Software, read
- Services/Services_bases/webhook_service/webhook.py — Drakkar-Software, read
- Trading/Mode/trading_view_signals_trading_mode/trading_view_signals_trading.py — Drakkar-Software, read
- octobot_services/constants.py — Drakkar-Software, read
- Webhook alerts — Gunbot, read
The catalogue next door
This page names a handful of products. The rest of them are in Crypto Charting Platforms & Libraries, each filled in against the same schema, with the fields to narrow it yourself.
Last updated . Corrected in place — an endpoint that moves is a bug on this page, not a new post.