Michael Ouroumis logoichael Ouroumis

Build a Real-Time Tesla Stock Price Tracker with JavaScript

Dark gradient background with a glowing turquoise-green line chart showing Tesla’s stock price trend, the bold text “TSLA” above the chart, and a subtle JavaScript “JS” logo in the lower right.

TL;DR: Build a live-updating Tesla (TSLA) stock price tracker in pure JavaScript by choosing a reliable API (either REST polling or WebSocket), setting up a minimal frontend project, fetching or subscribing to price updates, and rendering the data in a clean UI—optionally with Chart.js for a real-time chart. Ensure error handling and efficient DOM updates to keep your tracker performant and responsive.


Why Real-Time Stock Tracking Matters

Investors, traders, and enthusiasts often want instant visibility into stock movements to make timely decisions. Tesla’s (TSLA) price is especially volatile, and having a lightweight, web-based tracker can help you:

  • Stay Informed Instantly: See price changes as they happen, not minutes later.
  • Build Intuition: Observe how news events affect Tesla’s market value in real time.
  • Learn Modern JavaScript: Implement WebSocket or efficient polling, work with live data, and visualize changes smoothly.

By the end of this tutorial, you’ll understand how to integrate with a stock-price API, manage live updates, and present Tesla’s current price in your own frontend dashboard.


1. Choosing Your Data Source

1.1 REST Polling vs. WebSocket

Most free or freemium stock data providers offer two modes:

  • REST Polling: You periodically send HTTP requests (e.g., every 5 seconds) to fetch the latest TSLA quote. Simple to implement but can introduce latency and unnecessary network requests.
  • WebSocket Streaming: You open a persistent socket connection; the provider pushes new price updates instantly. Lower overhead and near-zero latency on price changes, but requires a provider that supports websockets.

For production-grade finance apps, WebSockets are preferred. In this tutorial, we’ll demonstrate both methods:

  1. REST Polling with a free-tier API endpoint.
  2. WebSocket subscription (if your chosen provider supports it).

1.2 Recommended APIs

  • Alpha Vantage (REST)

    • Free tier: 5 calls per minute.
    • Endpoint: https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=TSLA&apikey=YOUR_API_KEY
  • Finnhub (WebSocket + REST)

    • Free plan includes WebSocket streaming for stocks.

    • WebSocket endpoint: wss://ws.finnhub.io?token=YOUR_API_KEY

    • After connecting, send:

      { "type": "subscribe", "symbol": "TSLA" }

Tip: Sign up for a free account on your chosen service and copy your API key before proceeding.


2. Setting Up Your JavaScript Project

You can keep this minimal—no build steps required. We’ll use plain HTML, CSS, and a single script.js file.

  1. Create folder structure:

    real-time-tsla/
    ├── index.html
    ├── styles.css
    └── script.js
    
  2. Add a basic index.html:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>TSLA Live Tracker</title> <link rel="stylesheet" href="styles.css" /> </head> <body> <div id="tracker"> <h1>TSLA: $<span id="price">--.--</span></h1> <canvas id="priceChart" width="600" height="300"></canvas> </div> <script src="script.js"></script> </body> </html>
  3. Basic styles.css:

    body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #121212; color: #ffffff; } #tracker { text-align: center; } #price { color: #00ff00; font-size: 3rem; } canvas { margin-top: 1rem; background: #1e1e1e; border-radius: 8px; }

Now, let’s wire up script.js.


3. Fetching Data via REST Polling

If you’re on a free tier that doesn’t support WebSockets, we can poll every 5 seconds.

  1. Install Chart.js (optional) If you want a real-time chart, include Chart.js via CDN in index.html above your script.js:

    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="script.js"></script>
  2. Implement polling in script.js:

    // script.js const API_KEY = 'YOUR_ALPHA_VANTAGE_KEY' const SYMBOL = 'TSLA' const PRICE_ELEMENT = document.getElementById('price') // Optional: Chart.js setup let priceChart const ctx = document.getElementById('priceChart').getContext('2d') const chartData = { labels: [], datasets: [ { label: 'TSLA', data: [], borderColor: '#00ff00', fill: false }, ], } function initChart() { priceChart = new Chart(ctx, { type: 'line', data: chartData, options: { animation: false, scales: { x: { type: 'time', time: { unit: 'second', displayFormats: { second: 'HH:mm:ss' } }, }, y: { beginAtZero: false }, }, }, }) } async function fetchLatestPrice() { try { const url = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${SYMBOL}&apikey=${API_KEY}` const response = await fetch(url) const data = await response.json() const priceString = data['Global Quote']['05. price'] const price = parseFloat(priceString).toFixed(2) // Update DOM PRICE_ELEMENT.textContent = price // Update chart const now = new Date() chartData.labels.push(now) chartData.datasets[0].data.push(price) if (chartData.labels.length > 30) { chartData.labels.shift() chartData.datasets[0].data.shift() } priceChart.update() } catch (error) { console.error('Error fetching TSLA price:', error) } } // Initialize initChart() fetchLatestPrice() // Poll every 5 seconds setInterval(fetchLatestPrice, 5000)
  3. Explanation

    • We fetch Tesla’s latest price from Alpha Vantage’s GLOBAL_QUOTE endpoint.
    • Parse 05. price from the JSON response, format it, and inject into the <span id="price">.
    • Push new data points into Chart.js; keep only the last 30 entries to avoid infinite growth.
    • Poll every 5 seconds with setInterval.

Note: Free-tier APIs often have rate limits. If you exceed 5 calls/minute, you’ll receive a “Too Many Requests” error. Adjust your polling interval or upgrade to a paid plan as needed.


4. Implementing WebSocket for Live Updates

For truly real-time updates (sub-second latency), use a WebSocket-based provider such as Finnhub. Here’s how:

  1. Connect to Finnhub’s WebSocket

    // script.js (replace polling code) const API_KEY = 'YOUR_FINNHUB_KEY' const SYMBOL = 'TSLA' const PRICE_ELEMENT = document.getElementById('price') let priceChart function initChart() { const ctx = document.getElementById('priceChart').getContext('2d') priceChart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [ { label: 'TSLA', data: [], borderColor: '#00ff00', fill: false }, ], }, options: { animation: false, scales: { x: { type: 'time', time: { unit: 'second', displayFormats: { second: 'HH:mm:ss' } }, }, y: { beginAtZero: false }, }, }, }) } function connectWebSocket() { const socket = new WebSocket(`wss://ws.finnhub.io?token=${API_KEY}`) socket.addEventListener('open', () => { // Subscribe to TSLA socket.send(JSON.stringify({ type: 'subscribe', symbol: SYMBOL })) }) socket.addEventListener('message', (event) => { const message = JSON.parse(event.data) if (message.type === 'trade') { // message.data is an array of trade updates message.data.forEach((trade) => { const price = parseFloat(trade.p).toFixed(2) const timestamp = new Date(trade.t) updateUI(price, timestamp) }) } }) socket.addEventListener('error', (err) => { console.error('WebSocket error:', err) }) socket.addEventListener('close', () => { console.warn('WebSocket closed. Reconnecting in 5s...') setTimeout(connectWebSocket, 5000) }) } function updateUI(price, timestamp) { // Update price text PRICE_ELEMENT.textContent = price // Update chart const data = priceChart.data data.labels.push(timestamp) data.datasets[0].data.push(price) // Keep last 50 points to avoid heavy memory usage if (data.labels.length > 50) { data.labels.shift() data.datasets[0].data.shift() } priceChart.update() } // Initialize tracker initChart() connectWebSocket()
  2. Explanation

    • Create a WebSocket connection to Finnhub’s server, passing your API key as a query parameter.
    • Upon open, send a subscribe message for the symbol “TSLA”.
    • Listen for message events; parse the JSON, filter for type === 'trade', and iterate over message.data (each trade has p for price and t for timestamp).
    • Call updateUI(price, timestamp) on each trade: update the DOM and push to Chart.js.
    • Implement reconnection logic to handle dropped connections.

Pro Tip: WebSocket providers may bundle multiple trades in one payload. To avoid flooding, consider debouncing UI updates if you see hundreds of trades per second. For Tesla on high-volume days, you may receive dozens of trade updates per second.


5. Visualizing Data

If you skipped Chart.js, you can still show a simple list of recent prices or build a minimal SVG chart manually. However, Chart.js makes life easier:

  1. Customize Your Chart

    • Change line color: update borderColor in the dataset.
    • Disable point markers: add pointRadius: 0 under datasets[0].
    • Display moving average: add a second dataset where you compute the rolling average of the last n prices.
  2. Example: Adding a 30-Point Simple Moving Average (SMA)

    // After initializing priceChart in initChart() priceChart.data.datasets.push({ label: 'SMA (30)', data: [], borderColor: '#ff9900', borderDash: [5, 5], fill: false, pointRadius: 0, }) function computeSMA(dataArray, windowSize) { if (dataArray.length < windowSize) return null const windowSlice = dataArray.slice(-windowSize) const sum = windowSlice.reduce((acc, val) => acc + parseFloat(val), 0) return (sum / windowSize).toFixed(2) } function updateUI(price, timestamp) { PRICE_ELEMENT.textContent = price const chartData = priceChart.data // Push raw price chartData.labels.push(timestamp) chartData.datasets[0].data.push(price) // Compute and push SMA if enough points const smaValue = computeSMA(chartData.datasets[0].data, 30) chartData.datasets[1].data.push(smaValue) // Trim arrays if (chartData.labels.length > 50) { chartData.labels.shift() chartData.datasets[0].data.shift() chartData.datasets[1].data.shift() } priceChart.update() }

Note: The above SMA calculation will produce null until you have 30 data points. Chart.js will skip plotting null values.


6. Handling Edge Cases and Errors

  • API Rate Limits (Polling)

    • If you exceed the allowed calls per minute, your REST response may be blocked or return an error. Always check for error payloads and show a friendly message:

      if (data['Error Message'] || !data['Global Quote']) { console.warn('API limit likely reached or invalid response', data) return }
    • Consider backing off: defer the next fetchLatestPrice() call by a longer interval.

  • WebSocket Disconnections

    • Implement an exponential backoff when reconnecting. In our example, we used a fixed 5-second delay. For production, track the number of retries and increase the delay (e.g., 5s, 10s, 20s, up to a max).
  • Time Zone & Market Hours

    • U.S. equities trade from 9:30 AM to 4 PM Eastern Time (ET). Outside those hours, real-time data may not update, or you might get delayed quotes.
    • If building a global dashboard, display the local timestamp of each update or convert trade.t (UNIX milliseconds) into the user’s locale.
  • Data Spikes & Erroneous Quotes

    • Occasionally, providers can deliver an outlier price due to a bad tick. Filter out prices that deviate unrealistically from the previous price, e.g., ±5% in a single tick:

      function isValidPrice(newPrice, lastPrice) { if (!lastPrice) return true const delta = Math.abs(newPrice - lastPrice) / lastPrice return delta < 0.05 // less than 5% change } // In updateUI: const lastPrice = priceChart.data.datasets[0].data.slice(-1)[0] if (!isValidPrice(price, lastPrice)) return // skip this tick

7. Deploying Your Tracker

After development, you can deploy your tracker to any static-hosting provider:

  • GitHub Pages: Push your folder to a gh-pages branch or configure via repository settings.
  • Netlify / Vercel: Drag-and-drop your project folder or connect to a Git repository; automatic build isn’t necessary for plain HTML/CSS/JS.
  • Surge.sh: Install the CLI and run surge ./real-time-tsla.

Security Warning: Never expose REST API keys in client-side JavaScript for production. For REST polling, proxy requests through your own server (e.g., a simple Node.js Express endpoint that injects the API key). For WebSockets, some providers allow you to create time-limited tokens or restrict by domain. Always read your provider’s security guidelines.


Final Thoughts

  • Start Simple: If this is your first real-time app, begin with REST polling to grasp fetching and DOM updates, then migrate to WebSockets for low-latency streaming.

  • Optimize Performance: Only update the DOM when the price actually changes. Minimize Chart.js re-renders by batching updates (e.g., update every 500ms with the newest tick instead of every single tick).

  • Enhance Your UI: Add features like:

    • Toggle between a line chart and a candlestick chart.
    • Show yesterday’s close for comparison.
    • Display volume or trade size alongside price.
  • Keep Learning: Real-time data patterns you apply here translate to chat apps, dashboards, and collaborative tools.

With this setup, you now have a live, JavaScript-based tracker showing Tesla’s current stock price—perfect for embedding in your portfolio site or sharing with friends. Keep refining your UX, experiment with new charting libraries, and explore deeper financial data analysis to turn this simple tracker into a robust trading companion.

Enjoyed this post? Share: