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 webhook URL and the alert comments to paste into the alert; with JSON settings the message carries the bot's entry code and, optionally, the order parameters for that one trade:

{
  "code": "YOUR_ENTER_LONG_CODE",
  "orderType": "market",
  "amountPerTrade": "0.1",
  "amountPerTradeType": "percents"
}

code is doing more work than the rest: it is the only thing standing between the URL and anyone who learns it. What the message no longer carries is an age check. Under v1, switched off on 11 September 2026, the template had a secret and a max_lag — the largest delay accepted between timestamp and execution, 10 to 86,400 seconds, 300 by default — and a signal past it was treated as invalid. v2 runs on the engine it shares with WunderTrading, and its JSON guide documents neither field, so nothing in this chain guards against an order placed on a price from five minutes ago unless you put the check in front of it yourself. The rest of this page is about why that matters.

What the options are

Hosted, JSON in. 3Commas, above, runs signal bots on every paid plan, two of them on Starter; what the v2 free plan includes is not published. 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 code, 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 3Commas' v1 max_lag was 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.

  1. 3Commas

    Signal bots on every paid plan take JSON whose code field is the only credential. Since v2 replaced v1 in September 2026, no field refuses a stale signal.

    Hosted DCA, grid and signal bots on nine exchanges, relaunched in 2026 with WunderTrading.

    $20/moFree tier

  2. 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.

    €28/moFree tier

  3. 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

  4. 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 run on your own machine, sold to new buyers by the month.

    €29/mo

  5. 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

  1. How to configure webhook alerts — TradingView, read
  2. Compare plans — TradingView, read
  3. Delays in OncePerBarClose alerts — TradingView, read
  4. Alert was triggered too often and stopped — TradingView, read
  5. Pine Script v6 User Manual — Alerts — TradingView, read
  6. Pine Script v6 User Manual — Repainting — TradingView, read
  7. Signal bot: JSON file in Custom signal type — 3Commas,
  8. Signal Bot: Comprehensive JSON Guide — 3Commas,
  9. Webhook Signal Reference: Open, Increase, Reduce, Close, and Reverse — Altrady, read
  10. Services/Services_bases/trading_view_service/trading_view.py — Drakkar-Software, read
  11. Services/Services_bases/webhook_service/webhook.py — Drakkar-Software, read
  12. Trading/Mode/trading_view_signals_trading_mode/trading_view_signals_trading.py — Drakkar-Software, read
  13. octobot_services/constants.py — Drakkar-Software, read
  14. Webhook alerts — Gunbot, read

The catalogue next door

This page names a handful of products. The rest of them are in Crypto Charting Platforms & Screeners, 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.

Report an error on this page

Quote the line and say what it should be.

The vendor’s page, filing or documentation that says otherwise.

Only if you want to hear back. Never published.

Read by a person. It fixes a fact and moves nothing else.

Anything else — a question this page leaves open, a tool it should be compared with? Write to feedback@cryptomarkets.tools.