From 86803501b61492cc8035d108001dc474523139ff Mon Sep 17 00:00:00 2001 From: theovenvibe Date: Sun, 8 Mar 2026 05:34:16 +0530 Subject: [PATCH] fix: resolve sign-in authentication failure due to missing session and User-Agent The __auth method was using a bare requests.post() without a session or User-Agent header, causing TradingView to reject the request as bot traffic (returning rate_limit or silently failing). Changes: - Use requests.Session() to maintain cookies across requests - Add a browser-like User-Agent header to avoid bot detection - Visit the homepage before POST to /accounts/signin/ to pick up session cookies - Add Origin and Content-Type headers for proper CORS compliance - Add a single retry with 2s delay when rate-limited - Improve error logging to include the actual exception message - Remove duplicate json import --- tvDatafeed/main.py | 47 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/tvDatafeed/main.py b/tvDatafeed/main.py index de77ebc..c97b303 100644 --- a/tvDatafeed/main.py +++ b/tvDatafeed/main.py @@ -5,13 +5,15 @@ import random import re import string +import time import pandas as pd from websocket import create_connection import requests -import json logger = logging.getLogger(__name__) +_TV_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" + class Interval(enum.Enum): in_1_minute = "1" @@ -33,7 +35,11 @@ class TvDatafeed: __sign_in_url = 'https://www.tradingview.com/accounts/signin/' __search_url = 'https://symbol-search.tradingview.com/symbol_search/?text={}&hl=1&exchange={}&lang=en&type=&domain=production' __ws_headers = json.dumps({"Origin": "https://data.tradingview.com"}) - __signin_headers = {'Referer': 'https://www.tradingview.com'} + __signin_headers = { + 'Referer': 'https://www.tradingview.com', + 'Origin': 'https://www.tradingview.com', + 'Content-Type': 'application/x-www-form-urlencoded', + } __ws_timeout = 5 def __init__( @@ -64,7 +70,7 @@ def __init__( def __auth(self, username, password): - if (username is None or password is None): + if username is None or password is None: token = None else: @@ -72,11 +78,38 @@ def __auth(self, username, password): "password": password, "remember": "on"} try: - response = requests.post( - url=self.__sign_in_url, data=data, headers=self.__signin_headers) - token = response.json()['user']['auth_token'] + # Use a session with a proper User-Agent so TradingView + # does not reject us as bot traffic / rate-limit us. + session = requests.Session() + session.headers.update({"User-Agent": _TV_USER_AGENT}) + + # Visit the homepage first to pick up any cookies / + # session identifiers that TradingView expects. + session.get("https://www.tradingview.com/") + + response = session.post( + url=self.__sign_in_url, + data=data, + headers=self.__signin_headers, + ) + + resp_json = response.json() + + # If rate-limited, wait briefly and retry once. + if resp_json.get("code") == "rate_limit": + logger.warning("rate limited, retrying in 2 s …") + time.sleep(2) + response = session.post( + url=self.__sign_in_url, + data=data, + headers=self.__signin_headers, + ) + resp_json = response.json() + + token = resp_json['user']['auth_token'] + except Exception as e: - logger.error('error while signin') + logger.error(f'error while signin: {e}') token = None return token