DEV Community

tradingviewdonwloadforpc
tradingviewdonwloadforpc

Posted on

TradingView Alerts & Webhooks: Complete Developer Integration Guide (Python, Node.js, Go)

First, get TradingView installed on your PCtradingviewdownloadforpc.com — authorized Windows setup guide with screenshots.

Last updated: May 2026 | Author: Michael Hannah | Difficulty: Intermediate | Prerequisites: TradingView account, basic familiarity with REST APIs


TL;DR

TradingView processes alerts server-side and can deliver them as webhook HTTP POST requests to any publicly reachable URL. This lets you build event-driven trading infrastructure: Pine Script defines the signal, TradingView fires the alert, and your backend executes the logic — order placement, notifications, database logging, or workflow triggers. This guide covers the full stack from alert configuration to production-grade webhook receivers in Python, Node.js, and Go.


How TradingView Alerts Work (Architecture)

┌─────────────────────────┐
│  Pine Script Indicator  │   alertcondition() fires when condition is met
└────────────┬────────────┘
             │ alert event
             ▼
┌─────────────────────────┐
│  TradingView Servers    │   processes alert server-side (no local client needed)
└────────────┬────────────┘
             │ HTTP POST
             ▼
┌─────────────────────────┐
│  Your Webhook Endpoint  │   receives JSON payload, triggers downstream action
└────────────┬────────────┘
             │
     ┌───────┴───────┐
     ▼               ▼
┌─────────┐    ┌─────────────┐
│ Broker  │    │  Slack/DB/  │
│   API   │    │  Workflow   │
└─────────┘    └─────────────┘
Enter fullscreen mode Exit fullscreen mode

Key point: TradingView fires webhooks from its own servers. Your PC, browser, or desktop app does NOT need to be running for webhooks to fire. The TradingView desktop app only needs to be open for OS-level desktop notifications — webhooks are entirely server-side.


Alert Types Reference

Alert Type Trigger Condition Supports Webhook
Price crossing Asset crosses a set price level Yes
Price moving up/down Price moves by % or amount Yes
Crossing indicator Price crosses a plotted indicator Yes
Custom (alertcondition) Any boolean Pine Script expression Yes
Strategy entry/exit strategy.entry() / strategy.exit() fires Yes
Drawing alert Price crosses a manually drawn line Yes

Step 1: Configure an Alert on TradingView Desktop

With TradingView open on Windows (install guide):

Via keyboard shortcut:

  • Press Alt+A to open the Create Alert dialog instantly

Via chart right-click:

  • Right-click anywhere on the chart → "Add Alert on..."

In the alert dialog:

  1. Condition — select your indicator output or price action
  2. Value/threshold — set the trigger level
  3. Frequency — choose when the alert fires:
    • Once — fires once, then deactivates
    • Once per bar — once per closed bar meeting the condition
    • Once per bar close — fires at bar close only
    • Every time — fires on every tick where the condition is true (use carefully — can generate many requests)
  4. Expiration — set an end date/time for the alert to auto-deactivate
  5. Alert actions — check "Webhook URL" and paste your endpoint

The Webhook Payload

TradingView sends a plain HTTP POST with the body you define in the "Message" field of the alert dialog. You can embed dynamic placeholders that TradingView fills in at fire time:

Available Placeholders

Placeholder Type Description
{{ticker}} string Symbol ticker (e.g., BTCUSDT)
{{exchange}} string Exchange (e.g., BINANCE)
{{close}} number Current bar close price
{{open}} number Current bar open price
{{high}} number Current bar high price
{{low}} number Current bar low price
{{volume}} number Current bar volume
{{time}} string Bar open time (ISO 8601)
{{timenow}} string Current wall-clock time (ISO 8601)
{{interval}} string Chart timeframe (e.g., 60 for 1H)
{{plot_0}} number Value of the first plot() in the script

Example Alert Message (JSON format)

{
  "ticker":    "{{ticker}}",
  "exchange":  "{{exchange}}",
  "price":     {{close}},
  "volume":    {{volume}},
  "time":      "{{timenow}}",
  "interval":  "{{interval}}",
  "action":    "buy",
  "strategy":  "ema_cross"
}
Enter fullscreen mode Exit fullscreen mode

Note: TradingView does not set a Content-Type: application/json header by default. Your receiver should parse the raw body as JSON regardless of the incoming Content-Type.


Alert Limits by Plan

Plan Max Active Alerts Webhook Delay
Free 1 ~seconds
Essential 20 ~seconds
Plus 100 ~seconds
Premium 400 Priority queue

Step 2: Write the Webhook Receiver

Python (Flask)

from flask import Flask, request, abort
import json, os

app = Flask(__name__)
SHARED_SECRET = os.environ.get("WEBHOOK_SECRET", "change-me")

@app.route("/webhook", methods=["POST"])
def handle_tradingview_alert():
    raw_body = request.get_data()

    try:
        data = json.loads(raw_body)
    except json.JSONDecodeError:
        abort(400)

    # Verify shared secret embedded in payload
    if data.get("secret") != SHARED_SECRET:
        abort(403)

    ticker   = data.get("ticker", "UNKNOWN")
    price    = data.get("price", 0)
    action   = data.get("action", "").lower()
    strategy = data.get("strategy", "")

    print(f"[ALERT] {strategy} | {action.upper()} {ticker} @ {price}")

    if action == "buy":
        place_buy_order(ticker, price)
    elif action == "sell":
        place_sell_order(ticker, price)

    return {"status": "ok", "ticker": ticker, "action": action}, 200

def place_buy_order(ticker, price):
    # Implement your broker API call here
    print(f"BUY {ticker} @ {price}")

def place_sell_order(ticker, price):
    print(f"SELL {ticker} @ {price}")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
Enter fullscreen mode Exit fullscreen mode

Node.js (Express)

const express = require("express");
const app = express();
const SHARED_SECRET = process.env.WEBHOOK_SECRET || "change-me";

app.use(express.json({ type: "*/*" })); // Accept any Content-Type

app.post("/webhook", (req, res) => {
  const { ticker, price, action, strategy, secret } = req.body;

  if (secret !== SHARED_SECRET) {
    return res.status(403).json({ error: "Forbidden" });
  }

  console.log(`[ALERT] ${strategy} | ${action.toUpperCase()} ${ticker} @ ${price}`);

  if (action === "buy")  placeBuyOrder(ticker, price);
  if (action === "sell") placeSellOrder(ticker, price);

  res.json({ status: "ok", ticker, action });
});

function placeBuyOrder(ticker, price)  { console.log(`BUY  ${ticker} @ ${price}`); }
function placeSellOrder(ticker, price) { console.log(`SELL ${ticker} @ ${price}`); }

app.listen(3000, () => console.log("Listening on :3000"));
Enter fullscreen mode Exit fullscreen mode

Go (net/http)

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os"
)

type AlertPayload struct {
    Ticker   string  `json:"ticker"`
    Exchange string  `json:"exchange"`
    Price    float64 `json:"price"`
    Action   string  `json:"action"`
    Strategy string  `json:"strategy"`
    Secret   string  `json:"secret"`
}

var sharedSecret = envOr("WEBHOOK_SECRET", "change-me")

func envOr(key, fallback string) string {
    if v := os.Getenv(key); v != "" { return v }
    return fallback
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    var p AlertPayload
    if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
        http.Error(w, "Bad request", http.StatusBadRequest)
        return
    }
    if p.Secret != sharedSecret {
        http.Error(w, "Forbidden", http.StatusForbidden)
        return
    }
    log.Printf("[ALERT] %s | %s %s @ %.2f", p.Strategy, p.Action, p.Ticker, p.Price)
    w.Header().Set("Content-Type", "application/json")
    fmt.Fprintf(w, `{"status":"ok","ticker":"%s","action":"%s"}`, p.Ticker, p.Action)
}

func main() {
    http.HandleFunc("/webhook", webhookHandler)
    log.Println("Webhook server listening on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Pine Script Alert Conditions

Define the alert conditions in Pine Script so they appear in the TradingView alert dialog:

//@version=5
indicator("EMA Cross Alert System", overlay=true)

fast   = input.int(9,  "Fast EMA")
slow   = input.int(21, "Slow EMA")
secret = input.string("change-me", "Webhook Secret")

ema_fast = ta.ema(close, fast)
ema_slow = ta.ema(close, slow)

crossUp   = ta.crossover(ema_fast, ema_slow)
crossDown = ta.crossunder(ema_fast, ema_slow)

plot(ema_fast, "Fast EMA", color=color.green)
plot(ema_slow, "Slow EMA", color=color.red)

plotshape(crossUp,   "Buy",  shape.triangleup,   location.belowbar, color.green)
plotshape(crossDown, "Sell", shape.triangledown, location.abovebar, color.red)

// Build JSON payload strings
buyMsg  = '{"ticker":"' + syminfo.ticker + '","price":' + str.tostring(close) + ',"action":"buy","strategy":"ema_cross","secret":"' + secret + '"}'
sellMsg = '{"ticker":"' + syminfo.ticker + '","price":' + str.tostring(close) + ',"action":"sell","strategy":"ema_cross","secret":"' + secret + '"}'

alertcondition(crossUp,   title="EMA Bullish Cross", message=buyMsg)
alertcondition(crossDown, title="EMA Bearish Cross", message=sellMsg)
Enter fullscreen mode Exit fullscreen mode

After adding to chart: right-click → Add Alert → select "EMA Bullish Cross" or "EMA Bearish Cross" → paste your webhook URL → Save.


Step 4: Local Testing with ngrok

Before deploying to production, test your receiver locally:

# Terminal 1 — start your receiver
python app.py            # Flask on :5000
# or: node server.js     # Express on :3000
# or: go run main.go     # Go on :8080

# Terminal 2 — expose via ngrok
ngrok http 5000

# ngrok outputs something like:
# Forwarding  https://abc123.ngrok-free.app -> http://localhost:5000
Enter fullscreen mode Exit fullscreen mode

Paste the https://abc123.ngrok-free.app/webhook URL into TradingView's webhook field. Trigger the alert manually to confirm your server receives and logs the payload.


Production Deployment Checklist

  • [ ] Deploy receiver to a public host (VPS, AWS Lambda, Railway, Fly.io, etc.)
  • [ ] Use HTTPS — TradingView rejects plain HTTP webhook URLs
  • [ ] Implement a shared secret check (see examples above)
  • [ ] Add idempotency — TradingView may occasionally fire duplicate alerts; track processed timestamps
  • [ ] Return a 200 response within 3 seconds; process heavy work asynchronously
  • [ ] Log all incoming payloads for debugging and audit purposes
  • [ ] Monitor your active alert count against your plan limit
  • [ ] Set alert expiration dates to avoid stale alerts consuming your limit

Common Errors and Fixes

Error Cause Fix
Webhook never fires Endpoint is plain HTTP Use HTTPS only
403 from your server Secret mismatch Verify secret matches in Pine Script input and env var
Duplicate orders placed TradingView sent duplicate alerts Track processed timenow in Redis or DB
Server receives alert but returns 500 Exception in handler Add try/except around processing logic
Alert fires on every tick Frequency set to "Every time" Change to "Once per bar"
Server times out Heavy sync processing Return 200 immediately; offload work to a queue

Frequently Asked Questions

Q: Does TradingView's desktop app need to be running for webhooks to fire?
No. TradingView processes alerts and fires webhooks from its own servers. Your PC, browser tab, and desktop app can all be off — webhooks fire as long as your TradingView account is active and the alert has not expired.

Q: How quickly does TradingView fire a webhook after a condition is met?
Delivery is typically 1–5 seconds after the triggering bar closes. On the Premium plan, TradingView prioritizes alert processing. During high-traffic market events, there may be additional delay on lower-tier plans.

Q: Does TradingView support HTTPS-only webhook URLs?
Yes. TradingView requires HTTPS. Plain HTTP endpoints are silently rejected — no error message is shown in the TradingView UI.

Q: Does TradingView sign webhook payloads (like GitHub's HMAC signature)?
No. TradingView does not natively sign webhook payloads. The recommended pattern is to embed a shared secret in the JSON message body (shown in the Pine Script example above) and verify it server-side.

Q: Can I send different payloads for buy and sell signals from the same script?
Yes. Use separate alertcondition() calls with different message strings. When creating the alert in TradingView, select the specific condition you want for that alert action.

Q: What happens if my server returns a non-200 response?
TradingView does not retry failed webhook deliveries. If your endpoint returns a 5xx or times out, the delivery is dropped silently. Ensure your server responds with 200 quickly, even if processing continues asynchronously.

Q: Can I use TradingView webhooks with n8n or Zapier?
Yes. Both n8n and Zapier support custom webhook triggers. Create a webhook node in n8n or a "Webhooks by Zapier" trigger, copy the HTTPS URL, and paste it into TradingView's webhook field. Your alert payload will flow directly into your automation workflow.


Resources


By Michael Hannah — trading software analyst and Pine Script developer. Updated May 2026.

Top comments (0)