How to Use Webhooks for TradingView to Automate Trades
TradingView's free alert system can trigger real trades. Connect Pine Script alerts to a webhook endpoint and auto-execute strategies on any exchange in minutes.
Builder of AI agents, crypto trading bots, and open-source automation tools. Sharing practical guides on how to build, deploy, and profit from AI and DeFi technology.
TradingView has over 50 million users โ many use it for charting but don't know its alerts can execute real trades. This guide shows you how to connect TradingView alerts to live trading in 15 minutes.
How It Works
TradingView can send an HTTP POST request (webhook) to any URL when an alert fires. Your server receives this webhook and executes the trade.
TradingView Alert โ HTTP POST โ Your Server โ Exchange API
Step 1: Create the Alert in TradingView
Option A: Simple condition alert
- Open BTC/USDT chart
- Click the Alert button (clock icon) โ Create Alert
- Condition: "RSI(14)" crosses below "30"
- Webhook URL:
https://your-server.com/trade?secret=abc123 - Message body (JSON):
{
"action": "buy",
"symbol": "BTCUSDT",
"price": "{{close}}",
"time": "{{time}}"
}
Option B: Pine Script strategy alert
Add this to your Pine Script to trigger on specific signals:
//@version=5
indicator("RSI Alert Bot", overlay=false)
rsi = ta.rsi(close, 14)
// Alert when RSI crosses key levels
if ta.crossunder(rsi, 30)
alert('{"action":"buy","symbol":"' + syminfo.ticker + '","price":"' + str.tostring(close) + '"}', alert.freq_once_per_bar_close)
if ta.crossover(rsi, 70)
alert('{"action":"sell","symbol":"' + syminfo.ticker + '","price":"' + str.tostring(close) + '"}', alert.freq_once_per_bar_close)
plot(rsi)
hline(70, "Overbought", color.red)
hline(30, "Oversold", color.green)
Step 2: Minimal Webhook Server
from flask import Flask, request, jsonify
import ccxt, os, logging
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
exchange = ccxt.binance({
'apiKey': os.getenv('BINANCE_API_KEY'),
'secret': os.getenv('BINANCE_SECRET'),
'enableRateLimit': True,
})
if os.getenv('USE_TESTNET') == 'true':
exchange.set_sandbox_mode(True)
WEBHOOK_SECRET = os.getenv('WEBHOOK_SECRET', 'changeme')
@app.route('/trade', methods=['POST'])
def handle_trade():
if request.args.get('secret') != WEBHOOK_SECRET:
return jsonify({'error': 'Unauthorized'}), 401
data = request.json or {}
action = data.get('action', '').lower()
symbol = data.get('symbol', 'BTCUSDT')
logging.info(f"Signal: {action} {symbol} @ {data.get('price')}")
# Normalize symbol format
if '/' not in symbol:
symbol = symbol.replace('USDT', '/USDT')
try:
if action == 'buy':
balance = exchange.fetch_balance()['USDT']['free']
size = min(float(os.getenv('TRADE_SIZE_USDT', '50')), balance * 0.95)
if size < 10:
return jsonify({'status': 'skipped', 'reason': 'insufficient balance'})
order = exchange.create_market_buy_order(symbol, None, {'quoteOrderQty': size})
return jsonify({'status': 'bought', 'price': order['average'], 'qty': order['filled']})
elif action == 'sell':
base = symbol.split('/')[0]
qty = exchange.fetch_balance()[base]['free']
if qty < 0.0001:
return jsonify({'status': 'skipped', 'reason': 'no position'})
qty = float(exchange.amount_to_precision(symbol, qty))
order = exchange.create_market_sell_order(symbol, qty)
return jsonify({'status': 'sold', 'price': order['average'], 'qty': order['filled']})
return jsonify({'status': 'no action'})
except Exception as e:
logging.error(f"Trade failed: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/health')
def health():
return jsonify({'status': 'ok'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int(os.getenv('PORT', 8080)))
Step 3: Deploy Free in 5 Minutes
Railway.app (easiest):
# Create Procfile
echo "web: python app.py" > Procfile
# requirements.txt
echo "flask\nccxt\npython-dotenv\ngunicorn" > requirements.txt
# Deploy
railway login
railway init
railway up
Railway gives you a public HTTPS URL instantly. Paste it in TradingView's webhook field.
Configure via Environment Variables
Set these in your server's environment (Railway โ Variables):
BINANCE_API_KEY=your_key
BINANCE_SECRET=your_secret
WEBHOOK_SECRET=random_secret_string_here
TRADE_SIZE_USDT=100
USE_TESTNET=false
Testing Before Going Live
- Set
USE_TESTNET=trueand get Binance testnet credentials - Create a TradingView alert with your webhook URL
- Trigger it manually: TradingView โ Alert โ "Fire" button
- Check your server logs and testnet account
When you're confident it works, switch to real API keys and set USE_TESTNET=false.
Common Issues
"Order not found" on Binance: Symbol format mismatch. Make sure BTCUSDT becomes BTC/USDT in ccxt.
Webhook doesn't fire: TradingView needs the webhook URL to respond with 200 status within 5 seconds. Make sure your server is running and accessible.
Trade executes twice: Set alert.freq_once_per_bar_close in Pine Script to prevent firing on bar updates.
For a more complete implementation with stop-losses and monitoring, see our full trading bot guide.
Related Articles
How to Create a TradingView Strategy and Alert to Auto-Trade
4 min read
Crypto BotsHow to Use the Binance API: Complete Beginner Guide (2025)
8 min read
Crypto BotsToken Sniping Bot: How to Buy New Crypto Launches in the First Block
4 min read
Crypto BotsHow to Write a Python Script That Trades Crypto Automatically
7 min read