🎓 Tutorials

TradingView Webhook to Telegram Bot: Get Real-Time Alerts on Your Phone (2026 Setup Guide)

⚠️ Disclosure: Some links on this page are affiliate links. If you sign up through them, I may earn a commission — at no extra cost to you. I only review tools I actually use.
I run a USDJPY momentum strategy that fires alerts from a custom Pine Script indicator. For months, I relied on TradingView's built-in push notifications — until I missed a signal because my phone silenced TV notifications along with everything else in Focus Mode.

That's when I moved my alerts to Telegram. Telegram messages bypass most "do not disturb" settings, the notification sound is customizable, and I can forward signals to a private group where my trading journal bot also logs entries.

Setting this up took me about 20 minutes. Here's exactly how to do it.

What You Need Before Starting

That's it. No server to rent, no code to write, no API keys to manage beyond what Telegram gives you for free.

Step 1: Create Your Telegram Bot With BotFather

Every Telegram bot starts with BotFather — Telegram's official bot that creates other bots.

1. Open Telegram and search for @BotFather

2. Send the command /newbot 3. BotFather asks for a display name — I named mine TV Alerts 4. BotFather asks for a username — it must end in bot (e.g., my_tv_alerts_bot) 5. BotFather gives you an HTTP API token — copy it and store it somewhere safe

The token looks like this: 7123456789:AAHk3gJdKfZ8x9bWcDeFgHiJkLmNoPqRsT

Important: This token grants full control of your bot. Don't share it publicly or commit it to a GitHub repo.

Step 2: Get Your Telegram Chat ID

Your bot needs to know *where* to send messages. That means getting the numeric chat ID for your personal chat, group, or channel.

For Personal Messages

1. Start a conversation with your new bot — search for its username and press Start

2. Send any message to the bot (like "hello") 3. Open this URL in your browser, replacing YOUR_BOT_TOKEN with your actual token:

https://api.telegram.org/botYOUR_BOT_TOKEN/getUpdates

4. Look for "chat":{"id":123456789} — that number is your chat ID

For a Group Chat

1. Add your bot to the group

2. Send a message in the group that mentions the bot 3. Hit the same getUpdates URL — the chat ID for groups is negative (e.g., -1001234567890)

For a Channel

1. Add the bot as an administrator to your channel

2. Post something in the channel 3. Check getUpdates — the channel chat ID is also negative

I use a private group with two members: me and the bot. This way I have a searchable log of every alert, and I can add my spouse or trading partner later without reconfiguring anything.

Step 3: Choose Your Relay Method

Here's the thing TradingView's webhook documentation doesn't make obvious: TradingView webhooks send HTTP POST requests to a URL you specify, but you can't just paste the Telegram API URL directly because TradingView sends the alert message as raw text in the request body, not as a properly formatted Telegram API call.

You need a lightweight relay — something that receives the webhook from TradingView and forwards it to Telegram's sendMessage endpoint.

Here are three options, ranked by simplicity:

Option A: TradingFinder's Free Relay (Easiest — No Code)

TradingFinder built a free relay service specifically for this use case. The TradingView community has a popular indicator called "TradingView Telegram Webhook Alert" by TFlab that generates the webhook URL for you.

1. Go to TradingView → Indicators → search "TradingView Telegram Webhook Alert TFlab"

2. Add it to your chart 3. In the indicator settings, paste your bot token and chat ID 4. The indicator generates a webhook URL — copy it

The downside: you're routing your alerts through a third-party server. For price alerts and signal notifications, this is fine. For sending actual trade execution commands, I'd self-host.

Option B: Cloudflare Workers (Free, 5 Minutes, Your Own Relay)

This is what I use. Cloudflare Workers gives you 100,000 free requests per day — more than enough for trading alerts.

Create a file called worker.js:

export default {
  async fetch(request, env) {
    if (request.method !== "POST") {
      return new Response("Send a POST request", { status: 405 });
    }

    const body = await request.text();
    
    // Parse the incoming message
    // TradingView sends the alert message as plain text in the body
    const message = body.trim();
    
    if (!message) {
      return new Response("Empty message", { status: 400 });
    }

    // Forward to Telegram
    const telegramUrl = `https://api.telegram.org/bot${env.BOT_TOKEN}/sendMessage`;
    
    const response = await fetch(telegramUrl, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        chat_id: env.CHAT_ID,
        text: message,
        parse_mode: "HTML"
      })
    });

    if (response.ok) {
      return new Response("Sent", { status: 200 });
    } else {
      const error = await response.text();
      return new Response(`Telegram error: ${error}`, { status: 502 });
    }
  }
};

Deploy it:

npx wrangler init tv-telegram-relay
# Replace the generated worker.js with the code above
npx wrangler secret put BOT_TOKEN
# Paste your bot token when prompted
npx wrangler secret put CHAT_ID
# Paste your chat ID when prompted
npx wrangler deploy

Your relay URL will be something like https://tv-telegram-relay.your-subdomain.workers.dev — use this as the webhook URL in TradingView.

Why I prefer this: It's free, it runs on Cloudflare's edge (low latency globally), and my bot token never touches TradingView's servers. The secrets are stored encrypted in Cloudflare.

Option C: Google Apps Script (Free, No Terminal Needed)

If you don't have a Cloudflare account and want something browser-only:

1. Go to script.google.com

2. Create a new project 3. Paste this code:

function doPost(e) {
  const BOT_TOKEN = "YOUR_BOT_TOKEN";
  const CHAT_ID = "YOUR_CHAT_ID";
  
  const message = e.postData.contents;
  
  const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`;
  
  UrlFetchApp.fetch(url, {
    method: "post",
    contentType: "application/json",
    payload: JSON.stringify({
      chat_id: CHAT_ID,
      text: message,
      parse_mode: "HTML"
    })
  });
  
  return ContentService.createTextOutput("OK");
}

4. Deploy → New Deployment → Web app → Execute as "Me" → Access "Anyone"

5. Copy the deployment URL Downsides: Google Apps Script has cold-start latency (1-3 seconds), and the free tier has daily quota limits. For a handful of alerts per day, it works. For high-frequency signals, use Cloudflare Workers.

Step 4: Configure the TradingView Alert

Now the fun part — connecting TradingView to your relay.

1. Open your chart on TradingView

2. Right-click on an indicator or price level → Add Alert (or press Alt+A) 3. Set your condition (price crossing a level, indicator signal, Pine Script alertcondition, etc.) 4. Under Notifications, check Webhook URL 5. Paste your relay URL 6. In the Message field, type your alert message

Basic Alert Message

🔔 USDJPY Alert
Price crossed above 150.000
Time: {{timenow}}

Advanced Alert With Dynamic Placeholders

TradingView supports built-in placeholders that get replaced when the alert fires:

💡 TradingView

Like what you're reading? Try it yourself — this link supports ChartedTrader at no cost to you.

Try TradingView — Get Up to $30 Off Your First Plan →

📊 <b>{{ticker}}</b> Alert
Action: {{strategy.order.action}}
Price: {{close}}
Time: {{timenow}}
Exchange: {{exchange}}
Interval: {{interval}}

Here's my actual alert message template for USDJPY momentum signals:

🚀 <b>Signal: {{ticker}}</b>

Direction: {{strategy.order.action}}
Entry Price: {{close}}
Timeframe: {{interval}}
Time: {{timenow}}

Strategy: Momentum Crossover

The tags work because our relay sends messages with parse_mode: "HTML" — Telegram renders them as bold text.

Available TradingView Placeholders

PlaceholderWhat It ReturnsExample
{{ticker}}Symbol nameUSDJPY
{{exchange}}Exchange nameOANDA
{{close}}Current close price149.523
{{open}}Current open price149.410
{{high}}Current high149.680
{{low}}Current low149.320
{{volume}}Current volume58234
{{time}}Bar time (UTC)2026-03-21T14:00:00Z
{{timenow}}Alert trigger time2026-03-21T14:32:15Z
{{interval}}Chart timeframe60 (for 1H)
{{strategy.order.action}}Buy or sellbuy
{{strategy.order.price}}Order fill price149.523
{{strategy.position_size}}Position size1000
{{strategy.market_position}}Long/short/flatlong
{{strategy.prev_market_position}}Previous positionflat

Step 5: Test the Complete Pipeline

Before trusting this with real trading signals:

1. Create a test alert on any chart — set the condition to trigger immediately (like "price crossing" a level that's already passed)

2. Wait for TradingView to fire the webhook 3. Check your Telegram — the message should appear within 1-5 seconds

If it doesn't arrive:

  • Check the webhook URL — make sure there's no trailing space or newline
  • Verify the bot token — try calling https://api.telegram.org/botYOUR_TOKEN/getMe in your browser. You should see your bot's info
  • Confirm the chat ID — send a message to the bot again and re-check getUpdates
  • Check relay logs — in Cloudflare Workers, go to Workers → your worker → Logs → Real-time. You'll see every incoming request and any errors
Common gotcha: TradingView sends the webhook on alert trigger, not on every bar. If your alert condition is "crossing," it fires once. If you want repeated notifications, use "greater than" or set the alert to "Once Per Bar Close."

Real-World Setup: Multi-Alert Trading Dashboard

Once the basic pipeline works, you can get creative. Here's my setup:

Separate Channels for Different Signal Types

I run three Telegram groups, each with its own bot relay:

  • 📈 Entry Signals — only fires when my momentum strategy generates a buy/sell signal
  • ⚠️ Risk Alerts — fires on unusual volatility, drawdown thresholds, or position size warnings
  • 📋 Daily Summary — fires once per day with a strategy performance snapshot
Each group has a different Cloudflare Worker endpoint, so I can tune the formatting and add logic (like suppressing duplicate alerts within 5 minutes).

Formatted Trade Card

Here's the template I use for entry signals — it creates a clean, scannable card in Telegram:

🟢 <b>LONG Signal</b>

Pair: <b>{{ticker}}</b>
Entry: {{close}}
Timeframe: {{interval}} min

📊 Momentum Score: see chart
⏰ {{timenow}}

<i>Auto-generated by TradingView Webhook</i>

Adding Emoji for Quick Visual Scanning

I use {{strategy.order.action}} to control the emoji prefix in my Cloudflare Worker:

// In your worker.js, before sending to Telegram:
let formattedMessage = message;
if (message.toLowerCase().includes("buy")) {
  formattedMessage = "🟢 " + formattedMessage;
} else if (message.toLowerCase().includes("sell")) {
  formattedMessage = "🔴 " + formattedMessage;
}

This makes it obvious at a glance whether you're looking at a long or short signal when you check your phone.

Webhook Alerts With Pine Script

If you write your own indicators, you can trigger alerts from Pine Script using alertcondition() or the newer alert() function:

//@version=6
indicator("Momentum Alert Example", overlay=true)

// Simple momentum crossover
fastMA = ta.sma(close, 10)
slowMA = ta.sma(close, 50)

bullishCross = ta.crossover(fastMA, slowMA)
bearishCross = ta.crossunder(fastMA, slowMA)

// Method 1: alertcondition (older, works with manual alert setup)
alertcondition(bullishCross, "Bullish Crossover", "🟢 BUY Signal on {{ticker}} at {{close}}")
alertcondition(bearishCross, "Bearish Crossover", "🔴 SELL Signal on {{ticker}} at {{close}}")

// Method 2: alert() function (newer, fires automatically from strategy)
if bullishCross
    alert("🟢 BUY Signal on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)

if bearishCross
    alert("🔴 SELL Signal on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)

Key difference: alertcondition() requires you to manually create an alert on the chart and select the condition. alert() fires automatically when the script runs — just set up one alert with "Any alert() function call" as the condition and your webhook URL. The alert() approach is cleaner for strategies with multiple signal types.

Troubleshooting Common Issues

Alert Fires But Telegram Message Never Arrives

1. Check your relay's logs. If TradingView successfully sent the webhook but Telegram rejected it, you'll see the error

2. Most common cause: bot token expired or was regenerated. Go back to BotFather → /mytoken to check 3. Second most common: chat ID changed because you recreated the group. Re-fetch it from getUpdates

Messages Arrive With Delay (30+ Seconds)

  • If using Google Apps Script, cold starts cause 2-5 second delays. Switch to Cloudflare Workers for consistent sub-second delivery
  • If using Cloudflare Workers and still seeing delays, the issue is likely on TradingView's side — webhook delivery isn't instant, especially during high-volume market events. Typical latency is 1-10 seconds

Telegram Shows "Bad Request: can't parse entities"

Your HTML formatting has an error. Common mistakes:

  • Unclosed tags — every needs a
  • Using
    for line breaks — Telegram HTML doesn't support
    . Just use actual newlines in your message
  • Using unsupported tags — Telegram only supports: , , , , ,
    , 
Fix: switch parse_mode from "HTML" to "Markdown" or remove formatting entirely to debug.

Alert Fires Multiple Times

Check your alert settings in TradingView:

  • Once Per Bar Close — fires once when the bar closes. Best for strategies
  • Once Per Bar — fires once when the condition first becomes true within a bar. Can re-fire if the condition flips
  • Every Time Condition Is Met — fires on every tick where the condition is true. This will spam your Telegram
For trading signals, always use Once Per Bar Close. For price level alerts (like "BTC above 100K"), Only Once is what you want.

Cost Breakdown

ComponentCostNotes
TradingView Essential$12.95/moMinimum plan for webhooks (get a discount here)
Telegram BotFreeNo limits on messages
Cloudflare WorkersFree100K requests/day on free tier
Total$12.95/moOr less with annual billing
The only paid component is the TradingView plan — and you're probably already paying for it if you're running indicators and alerts. The webhook feature alone justifies upgrading from the free plan.

What Comes Next: From Alerts to Automation

Getting alerts on Telegram is step one. The natural next step is acting on those alerts automatically:

I started with Telegram alerts only, graduated to manual execution on seeing the signal, and eventually built a fully automated pipeline. The Telegram alerts are still running as a monitoring layer — I get notified of every signal whether or not the bot executes it.

FAQ

Can I use webhooks on the TradingView free plan?

No. Webhooks require the Essential plan or higher. The free plan supports email, push notifications, and pop-up alerts — but not webhooks. Check current TradingView pricing here.

Is there a limit on how many webhook alerts I can have?

Yes, but it's generous. Essential allows 20 active alerts, Plus allows 100, Premium allows 400, and Expert/Ultimate allow more. Each alert can have a webhook attached.

Can I send alerts to multiple Telegram groups?

Not directly from one TradingView alert — each alert has one webhook URL. But you can modify your relay to forward to multiple chat IDs:

const chatIds = [env.CHAT_ID_1, env.CHAT_ID_2, env.CHAT_ID_3];

await Promise.all(chatIds.map(chatId =>
  fetch(telegramUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ chat_id: chatId, text: message, parse_mode: "HTML" })
  })
));

Will this work for crypto, stocks, and forex?

Yes. TradingView webhooks fire for any instrument — crypto, forex, stocks, futures, indices. The alert is tied to the chart and condition, not the asset class.

How reliable is this? Will I miss signals?

In 6+ months of running this setup with Cloudflare Workers, I've had zero missed alerts. TradingView's webhook delivery is reliable, and Cloudflare Workers has 99.99% uptime. The only scenario where you'd miss a signal is if TradingView itself has an outage, which is rare.

That said, don't rely on *any* single notification method for critical trading decisions. I keep TradingView push notifications enabled as a backup alongside Telegram.

---

*Disclosure: This article contains affiliate links to TradingView. I use TradingView daily for chart analysis and alert management. If you sign up through my link, I may earn a commission at no extra cost to you.*

TradingView

Ready to get started? Use the link below — it helps support ChartedTrader at no cost to you.

Try TradingView — Get Up to $30 Off Your First Plan →
📈

About the author

I'm a systematic trader running live strategies on IB (USDJPY momentum) and Hyperliquid (crypto perps). Every tool reviewed here is something I've used with real capital. Questions? Reach out.

📚 Related Articles

🎓 Tutorials

TradingView Free Plan Indicator Limit: How to Combine RSI, EMA, and MACD Into One Pine Script (2026)

Hit TradingView's 2-indicator limit on the free plan? Learn how to combine RSI, EMA, and MACD into a single all-in-one Pine Script v6 indicator — with full copy-paste code, visual customization tips, and a clear upgrade path when you outgrow the workaround.

March 23, 2026 ⏱ 10 min read
🎓 Tutorials

TradingView Pine Script SuperTrend Strategy: Build a Custom Indicator Step by Step (2026)

Learn how to build a custom SuperTrend strategy indicator in Pine Script v6 with complete code. Includes RSI filter, multi-timeframe confirmation, stop loss/take profit, and backtesting setup for TradingView.

March 21, 2026 ⏱ 17 min read
🎓 Tutorials

TradingView Pine Script Multi-Chart Layout: Display Multiple Panels from One Indicator

Build a single Pine Script indicator that displays data across multiple chart panels using force_overlay, plot splits, and request.security.

March 20, 2026 ⏱ 10 min read

📬 Get weekly trading insights

Real trades, honest reviews, no fluff. One email per week.