When most traders or developers hear the name yfinance, they think of pulling historical stock data for analysis or backtesting. But now many know this hidden gem in yfinance: WebSocket support for live market data.

That means you can now stream real-time price updates for US stocks directly from Yahoo Finance with just a few lines of Python. And Even better one can build their own Alert Management system.
In this article, we’ll walk through how to use yf.WebSocket() to subscribe to live prices and explore a simple way to manage WebSocket connections using something called a context manager.
Why WebSockets?
Markets are real-time. Your system should be too.
Instead of polling for updates, we use persistent WebSocket connections to stream live prices from Yahoo Finance. No lag. No refreshes.
Getting Started
Make sure you’re running the latest version of yfinance.
pip install --upgrade yfinance
Once installed, create a Python file called realtimedata.py.
Sample Code Using WebSocket
Here’s a simple script that connects to Yahoo Finance’s WebSocket feed and prints live updates for AAPL and NVDA.
import yfinance as yf
def message_handler(message):
print("Received message:", message)
with yf.WebSocket() as ws:
ws.subscribe(["AAPL", "NVDA"])
ws.listen(message_handler)
This example uses what’s called a context manager. Let’s pause here and understand what that actually means.
What is a Context Manager?
In Python, a context manager is a built-in way to manage resources—like file handles, database connections, or in our case, WebSocket connections.
The key advantage of using a context manager is that it handles setup and teardown for you automatically. That means:
- It opens the WebSocket connection.
- It listens to live data.
- And when the block ends—or if something goes wrong—it gracefully closes the connection without leaving anything hanging.
The with statement is Python’s way of saying: “Do everything inside this block, and then clean up afterward, no matter what happens.”
Without a context manager, you’d have to remember to manually close the WebSocket using something like ws.close()—which you might forget to do during an exception or keyboard interrupt.
Alternate Version Without a Context Manager
If you prefer doing things manually, here’s how it looks without the with block:
import yfinance as yf
def message_handler(message):
print("Received message:", message)
ws = yf.WebSocket()
ws.subscribe(["AAPL", "NVDA"])
ws.listen(message_handler)
# You need to manually call ws.close() when done
This gives you more control, but it also comes with more responsibility.
Sample Output
When you run the script, it will continuously print updates like:
Connected to WebSocket.
Subscribed to symbols: ['AAPL', 'NVDA']
Listening for messages...
Received message: {'id': 'AAPL', 'price': 219.2684, 'time': '1754589807000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 2.8101785, 'day_volume': '62590455', 'change': 5.993408, 'last_size': '108', 'price_hint': '2'}
Received message: {'id': 'NVDA', 'price': 179.815, 'time': '1754589807000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 0.22015621, 'day_volume': '107894730', 'change': 0.39500427, 'last_size': '710', 'price_hint': '2'}
Received message: {'id': 'AAPL', 'price': 219.265, 'time': '1754589808000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 2.808583, 'day_volume': '62590757', 'change': 5.9900055, 'last_size': '100', 'price_hint': '2'}
Received message: {'id': 'NVDA', 'price': 179.8199, 'time': '1754589808000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 0.22288616, 'day_volume': '107896720', 'change': 0.39990234, 'last_size': '100', 'price_hint': '2'}
Received message: {'id': 'AAPL', 'price': 219.27, 'time': '1754589809000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 2.8109298, 'day_volume': '62592258', 'change': 5.9950104, 'last_size': '100', 'price_hint': '2'}
Received message: {'id': 'NVDA', 'price': 179.81, 'time': '1754589809000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 0.21736674, 'day_volume': '107898533', 'change': 0.3899994, 'last_size': '200', 'price_hint': '2'}
Received message: {'id': 'AAPL', 'price': 219.2799, 'time': '1754589809000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 2.815573, 'day_volume': '62592879', 'change': 6.0049133, 'last_size': '268', 'price_hint': '2'}
Received message: {'id': 'NVDA', 'price': 179.82, 'time': '1754589810000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 0.22294569, 'day_volume': '107900351', 'change': 0.40000916, 'last_size': '233', 'price_hint': '2'}
Received message: {'id': 'AAPL', 'price': 219.28, 'time': '1754589810000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 2.8156161, 'day_volume': '62593164', 'change': 6.005005, 'last_size': '100', 'price_hint': '2'}
Received message: {'id': 'NVDA', 'price': 179.82, 'time': '1754589810000', 'exchange': 'NMS', 'quote_type': 8, 'market_hours': 1, 'change_percent': 0.22294569, 'day_volume': '107900529', 'change': 0.40000916, 'price_hint': '2'}
Each message is a dictionary with useful fields such as:
id: Ticker symbolprice: Last traded priceday_volume: Total volume so farchange_percent: Percent change from previous closeexchange: e.g., NASDAQ
What You Can Build With This
- Live price tickers
- Trading dashboards
- Real-time data feeds for machine learning models
- Signal generation tools
- Simple backtest loggers that collect ticks
This works great for solo traders, hobby projects, or small-scale dashboards. But note that it’s not intended for production-level algo trading or institutional systems.
Real-Time Stock Alerts with yfinance and WebSockets
What if your trading system reacted as fast as the market moved?
That’s the idea behind the YFinance Alert Manager—a real-time alert system built using Python, WebSockets, and a minimalist backend.
Smarter Alerts, Not Spam
Traditional alerts trigger endlessly when prices fluctuate around a threshold.
We fixed that with auto-pausing alerts—they fire once, pause, and wait for your signal to reactivate.
Add visual cues (green for bullish, red for bearish, blue for targets), and you’ve got a system that speaks your language.
State That Persists
Browser refresh? No problem.
Our system tracks:
- Client state (UI + live prices)
- Server state (active alerts + connections)
- Database state (configs + history)
Everything syncs automatically, so you never lose context.
Takeaways
- Real-time alerts without polling
- No spam, just actionable signals
- Fully open-source and lightweight
Explore the code and run it yourself:
GitHub – YFinance Alert Manager