tradingview-screener
is a Python package that allows you to create custom stock screeners using TradingView's official
API. This package retrieves data directly from TradingView without the need for web scraping or HTML parsing.
- Access Over 3000 Fields: Retrieve data, including OHLC, indicators, and fundamental metrics.
- Multiple Markets: Screen equities, crypto, forex, futures, and bonds.
- Customizable Timeframes: Choose timeframes like 1 minute, 5 minutes, 1 hour, or 1 day for each field.
- Filter and sort the results using a SQL-like syntax, with support for And/Or operators for advanced filtering.
Install the package via pip:
pip install tradingview-screener
Here’s a simple example to get you started:
from tradingview_screener import Query
(Query()
.select('name', 'close', 'volume', 'market_cap_basic')
.get_scanner_data())
Output:
(17580,
ticker name close volume market_cap_basic
0 NASDAQ:NVDA NVDA 127.25 298220762 3.130350e+12
1 AMEX:SPY SPY 558.70 33701795 NaN
2 NASDAQ:TSLA TSLA 221.10 73869589 7.063350e+11
3 NASDAQ:QQQ QQQ 480.26 29102854 NaN
4 NASDAQ:AMD AMD 156.40 76693809 2.531306e+11
.. ... ... ... ... ...
45 NASDAQ:PDD PDD 144.22 8653323 2.007628e+11
46 NYSE:JPM JPM 214.52 5639973 6.103447e+11
47 NYSE:JNJ JNJ 160.16 7274621 3.855442e+11
48 NASDAQ:SQQQ SQQQ 7.99 139721164 NaN
49 NASDAQ:ASTS ASTS 34.32 32361315 9.245616e+09
[50 rows x 5 columns])
By default, the result is limited to 50 rows. You can adjust this limit, but be mindful of server load and potential bans.
A more advanced query:
from tradingview_screener import Query, col
(Query()
.select('name', 'close', 'volume', 'relative_volume_10d_calc')
.where(
col('market_cap_basic').between(1_000_000, 50_000_000),
col('relative_volume_10d_calc') > 1.2,
col('MACD.macd') >= col('MACD.signal')
)
.order_by('volume', ascending=False)
.offset(5)
.limit(25)
.get_scanner_data())
To access real-time data, you need to pass your session cookies, as even free real-time data requires authentication.
You can run this query to get an overview on the update_mode
you get for each exchange:
from tradingview_screener import Query
_, df = Query().select('exchange', 'update_mode').limit(1_000_000).get_scanner_data()
df.groupby('exchange')['update_mode'].value_counts()
exchange update_mode
AMEX delayed_streaming_900 3255
NASDAQ delayed_streaming_900 4294
NYSE delayed_streaming_900 2863
OTC delayed_streaming_900 7129
You can load the cookies from your local browser using rookiepy
:
-
Install
rookiepy
:pip install rookiepy
-
Load the cookies:
import rookiepy cookies = rookiepy.to_cookiejar(rookiepy.chrome(['.tradingview.com'])) # replace chrome() with your browser
-
Pass the cookies when querying:
Query().get_scanner_data(cookies=cookies)
Now, if you re-run the update mode check:
_, df = Query().select('exchange', 'update_mode').limit(1_000_000).get_scanner_data(cookies=cookies)
df.groupby('exchange')['update_mode'].value_counts()
exchange update_mode
AMEX streaming 3256
NASDAQ streaming 4286
NYSE streaming 2860
OTC delayed_streaming_900 7175
We now get live-data for all exchanges except OTC
.
Click to unfold example
-
Go to TradingView
-
Open the developer tools (
Ctrl + Shift + I
) -
Navigate to the
Application
tab. -
Go to
Storage > Cookies > https://www.tradingview.com/
-
Copy the value of
sessionid
-
Pass it in your query:
cookies = {'sessionid': '<your-session-id>'} Query().get_scanner_data(cookies=cookies)
Click to unfold example
While it's possible to authenticate directly via API, TradingView has restrictions on login frequency, which may result
in CAPTCHA requests and account flagging (meaning this method won't work again until the cooldown expires and the CAPTCHA
is gone).
If you wish to proceed, here’s how:
from http.cookiejar import CookieJar
import requests
from tradingview_screener import Query
def authenticate(username: str, password: str) -> CookieJar:
session = requests.Session()
r = session.post(
'https://www.tradingview.com/accounts/signin/',
headers={'User-Agent': 'Mozilla/5.0', 'Referer': 'https://www.tradingview.com'},
data={'username': username, 'password': password, 'remember': 'on'},
timeout=60,
)
r.raise_for_status()
if r.json().get('error'):
raise Exception(f'Failed to authenticate: \n{r.json()}')
return session.cookies
cookies = authenticate('<your-username-or-email>', '<your-password>')
Query().get_scanner_data(cookies=cookies)
...
This package is designed to be future-proof. All columns and markets are documented on the website, which is updated daily via a GitHub Actions script, reducing dependency on hardcoded values.
When using methods like select()
or where()
, the Query
object constructs a dictionary representing the API
request. Here’s an example of the dictionary generated:
{
'markets': ['america'],
'symbols': {'query': {'types': []}, 'tickers': []},
'options': {'lang': 'en'},
'columns': ['name', 'close', 'volume', 'relative_volume_10d_calc'],
'sort': {'sortBy': 'volume', 'sortOrder': 'desc'},
'range': [5, 25],
'filter': [
{'left': 'market_cap_basic', 'operation': 'in_range', 'right': [1000000, 50000000]},
{'left': 'relative_volume_10d_calc', 'operation': 'greater', 'right': 1.2},
{'left': 'MACD.macd', 'operation': 'egreater', 'right': 'MACD.signal'},
],
}
The get_scanner_data()
method sends this dictionary as a JSON payload to the TradingView API,
allowing you to query data using SQL-like syntax without knowing the specifics of the API.
I’m actively looking for Data Engineering or Backend Development roles, preferably in NYC—but I’m flexible with remote or freelance work too. If you’ve got something awesome in mind, let’s talk!