Fetch real-time data from 100+ websites,No development or maintenance required.
Over 100 million real residential IPs from genuine users across 190+ countries.
SCRAPING SOLUTIONS
Get accurate and in real-time results sourced from Google, Bing, and more.
With 120+ prebuilt and custom scrapers ready for any use case.
No blocks, no CAPTCHAs—unlock websites seamlessly at scale.
Execute scripts in stealth browsers with full rendering and automation
PROXY INFRASTRUCTURE
Over 100 million real residential IPs from genuine users across 190+ countries.
Reliable mobile data extraction, powered by real 4G/5G mobile IPs.
For time-sensitive tasks, utilize residential IPs with unlimited bandwidth.
Fast and cost-efficient IPs optimized for large-scale scraping.
SCRAPING SOLUTIONS
PROXY INFRASTRUCTURE
DATA FEEDS
Full details on all features, parameters, and integrations, with code samples in every major language.
LEARNING HUB
ALL LOCATIONS Proxy Locations
TOOLS
RESELLER
Get up to 50%
Contact sales:partner@thordata.com
Products $/GB
Fetch real-time data from 100+ websites,No development or maintenance required.
Get real-time results from search engines. Only pay for successful responses.
Execute scripts in stealth browsers with full rendering and automation.
Bid farewell to CAPTCHAs and anti-scraping, scrape public sites effortlessly.
Dataset Marketplace Pre-collected data from 100+ domains.
Over 100 million real residential IPs from genuine users across 190+ countries.
Reliable mobile data extraction, powered by real 4G/5G mobile IPs.
For time-sensitive tasks, utilize residential IPs with unlimited bandwidth.
Fast and cost-efficient IPs optimized for large-scale scraping.
Data for AI $/GB
Pricing $0/GB
Docs $/GB
Full details on all features, parameters, and integrations, with code samples in every major language.
Resource $/GB
EN $/GB
产品 $/GB
AI数据 $/GB
定价 $0/GB
产品文档 $/GB
资源 $/GB
简体中文 $/GB

When conducting data analysis, quantitative research, business intelligence, or content operations, you’ll often encounter the same challenge: the financial data you need is scattered across various web pages. Manually copying this data is not only slow but also prone to errors. If you need to continuously pull in “latest market quotes, valuation metrics, and key summary information” for analysis, dashboards, or internal reports, web scraping emerges as a highly practical technical approach. Among publicly accessible data sources, Yahoo Finance is frequently used—thanks to its broad coverage and high degree of information aggregation—to quickly obtain relevant data on U.S. stocks, ETFs, and indices.
Web scraping can be understood as: using a program to automatically access web pages or public APIs, then extracting the information you need from those pages and converting it into structured data (such as CSV, JSON, or database tables).
Python is typically used.requestsThe crawler initiates an HTTP request and obtains an HTML or JSON response. Obtaining the response is the first step in web scraping.
●HTML: UseBeautifulSoup/lxmlWait until the DOM structure is parsed, then locate the element and extract the text.
●JSON: Directly read the fields (generally more stable and recommended)
In real-world projects, the scraping script cannot just “run once”—it needs to “run daily and keep running continuously.” Therefore, the following is required:
●Timeout, Retry, and Exponential Backoff with Jitter
●Rate limiting, cache
●Logs, Monitoring, and Data Validation
●Compliance checks (robots, terms of service, access frequency control)
At its core, extracting financial data involves transforming “public information” into “computable data assets.” In U.S. tech teams, research groups, and content teams, this type of demand is extremely common, primarily due to the following factors.
Manually copying and pasting is not only time-consuming but also makes it difficult to ensure consistency. Web scraping allows you to turn data collection into a reusable program:
●Update on a daily schedule
●Automatically aggregate multiple stocks/ETFs
●Output a CSV/database table in a unified format.
For research or business analysis, it’s crucial to know “where the data comes from, when it was collected, and what the data-capture rules are.” The capture script can record:
●Requested URL and parameters
●Crawling Time and Response Status
●Original response summary (if necessary)
The scraped data can seamlessly flow into:
●Pandas data cleaning → Metric calculation → Backtesting/modeling
●BI Dashboard → Monitoring and Alerts
●Content System → Automatically Generate Financial Reports/Market Summaries
●Internal data platform → API as a service
What we need most is a data source that has broad coverage, commonly used fields, and a relatively low barrier to entry. Among publicly accessible financial information websites, Yahoo Finance often meets these basic requirements, making it the go-to choice for many engineering teams looking to quickly set up data access points.
Choosing Yahoo Finance doesn’t mean it’s “perfect,” but from an engineering perspective, it often has advantages in terms of “usability” and “cost-effectiveness.” Understanding these advantages can help you be clearer when designing your scraping solution: knowing what to scrape, how to scrape more reliably, and which boundaries need to be declared in advance.
A wide variety of asset classes, including stocks, ETFs, and indices.
For commonly traded assets in the U.S. market, Yahoo Finance typically provides a unified entry point, making it ideal for “batch fetching of multiple assets.”
Prefer JSON over stubbornly sticking with HTML.
Many key market data items—such as the latest price, price change percentage, and market capitalization—can be obtained through structured responses. Compared to parsing web page DOMs, parsing JSON fields is more stable and incurs lower maintenance costs.
Suitable for scaling from scripts to production-grade data pipelines.
You can join naturally:
●Session Reuse, Retry Backoff, Rate-Limited Caching
●Data Validation and Exception Isolation
●Output to CSV/database, and include version and source records.
When crawling, respect the site’s terms and robots.txt policy, and control the request rate to avoid placing undue burden on the service.
This section provides two actionable approaches and explains the applicable scenarios for each:
●Route A: Fetch JSON quote data from Yahoo Finance (more stable, suitable for market quotes and commonly used fields).
●Route B: Scrape the HTML of Yahoo Finance webpages and parse it (suitable for capturing page text or specific modules, but more susceptible to changes due to redesigns).
pip install requests beautifulsoup4 pandas
In real-world projects, it’s recommended that you additionally incorporate a logging library (such as...).loguru) and retry libraries (such astenacity), but to ensure the article can be “run with one click” by readers, we’ve kept dependencies to a minimum here.
The goal is to obtain common fields such as the latest price, price change, percentage change, market capitalization, and P/E ratio. When doing so, prioritize using a structured JSON format. Compared to HTML parsing, this approach is less likely to become invalid due to page updates or redesigns.
import pandas as pd
import time
urls_to_scrape = [
"https://www.amazon.com/dp/B0BZYCJK89",
"https://www.amazon.com/dp/B0BRXPR726",
]
results = []
for url in urls_to_scrape:
print(f"Scraping {url}...")
json_response = get_product_page(url)
if json_response:
product_data = parse_product_data(json_response)
if product_data:
product_data['url'] = url
results.append(product_data)
time.sleep(1)
if results:
df = pd.DataFrame(results)
df.to_csv('ecommerce_data.csv', index=False)
print("Scraping complete. Data saved to ecommerce_data.csv")
import time
import random
import requests
import pandas as pd
from datetime import datetime, timezone
SESSION = requests.Session()
SESSION.headers.update({
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/121.0.0.0 Safari/537.36",
"Accept": "application/json,text/plain,*/*",
})
def unix_to_iso(ts):
"""Convert a Unix timestamp (in seconds) to an ISO-format datetime string (UTC)."""
if ts is None:
return None
return datetime.fromtimestamp(ts, tz=timezone.utc).isoformat()
def fetch_yahoo_finance_quotes(tickers, max_retries=3, timeout=10):
"""
Fetch JSON data from the Yahoo Finance quote API, suitable for extracting market data and common fields.
"""
if isinstance(tickers, str):
tickers = [tickers]
url = "https://query1.finance.yahoo.com/v7/finance/quote"
params = {"symbols": ",".join(tickers)}
for attempt in range(1, max_retries + 1):
try:
resp = SESSION.get(url, params=params, timeout=timeout)
resp.raise_for_status()
data = resp.json()
results = data.get("quoteResponse", {}).get("result", [])
if not results:
raise ValueError("No quote data returned. Check ticker symbols or response format.")
rows = []
for item in results:
rows.append({
"symbol": item.get("symbol"),
"shortName": item.get("shortName"),
"regularMarketPrice": item.get("regularMarketPrice"),
"regularMarketChange": item.get("regularMarketChange"),
"regularMarketChangePercent": item.get("regularMarketChangePercent"),
"regularMarketTimeUTC": unix_to_iso(item.get("regularMarketTime")),
"marketCap": item.get("marketCap"),
"trailingPE": item.get("trailingPE"),
"currency": item.get("currency") # Add this line to include the currency field
})
return rows
except requests.exceptions.RequestException as e:
print(f"Attempt {attempt} failed: {e}. Retrying...")
time.sleep(random.uniform(1, 5)) # Random delay between retries
raise Exception("Max retries reached. Unable to fetch data.")get("currency"),
"source": "Yahoo Finance (quote endpoint)"
})
df = pd.DataFrame(rows)
# Simple data validation: The price field should be numeric and non-negative (can be enhanced as needed)
if "regularMarketPrice" in df.columns:
bad = df["regularMarketPrice"].isna() | (df["regularMarketPrice"] < 0)
if bad.any():
# Instead of directly terminating the process, you could choose to log an alert or record the exception
print("[warn] Some rows have invalid price values.")
return df
except Exception as e:
if attempt == max_retries:
raise
sleep_s = (2 ** attempt) + random.random()
print(f"[warn] attempt {attempt} failed: {e}. sleep {sleep_s:.2f}s then retry.")
timemsleep(sleep_s)
if __name__ == "__main__":
df = fetch_yahoo_finance_quotes(["AAPL", "MSFT", "NVDA"])
print(df)
# Save to disk for subsequent analysis, BI, or database loading
df.to_csv("yahoo_finance_quotes.csv", index=False)
)
When you need to extract text modules, descriptions, or certain types of information from a webpage that aren't readily available through structured APIs, HTML scraping can be used. However, web page structures may be updated, and CSS class names and DOM hierarchies could also change. Therefore, HTML parsing requires particularly “defensive coding” practices.
import requests
from bs4 import BeautifulSoup
def fetch_yahoo_finance_html(ticker, timeout=10):
url = f"https://finance.yahoo.com/quote/{ticker}"
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/121.0.0.0 Safari/537.36"
}
resp = requests.get(url, headers=headers, timeout=timeout)
resp.raise_for_status()
return resp.text
def parse_page_title(html):
soup = BeautifulSoup(html, "html.parser")
title = soup.title.get_text(strip=True) if soup.title else None
return {"page_title": title}
if __name__ == "__main__":
html = fetch_yahoo_finance_html("AAPL")
print(parse_page_title(html))
This HTML parsing example demonstrates only the “general and more reliable node (title).” If you’re looking to scrape dynamic data such as prices, percentage changes, and so on, in many cases the final rendered result isn’t actually included in the HTML source code. In such situations, we recommend:
●Return to route A using the JSON interface.
●Or locate the actual data request in the browser’s developer tools (Network panel), then use...requestsCall
To better align with EEAT and the “Helpful Content” guidelines, you can add the following practices to your article (and we also recommend implementing them in your code repository):
●The same ticker is not fetched repeatedly within a short period of time (e.g., cached for 5 minutes).
●When performing batch crawling, control concurrency and interval (e.g., introduce a random jitter of 0.5 to 2 seconds between each request).
Log: Capture time, symbols, status codes, elapsed time, and field missing rate.
When the occurrence of missing fields suddenly increases, it often indicates a change in the interface structure or policy.
●Data may be delayed (especially for non-real-time quotes).
●The field may be empty (depending on the underlying asset and trading session).
●This example in the article is intended solely for research and educational purposes and does not constitute investment advice.
In this tutorial, you’ve learned why Yahoo Finance is one of the most commonly used and information-rich sources for financial data, and you’ve grasped the core concepts for extracting data from it. We’ve focused on demonstrating how to quickly build a web crawler using Python to scrape basic information such as stock quotes—actually, the implementation isn’t complicated at all; just a few lines of code are sufficient to fetch the data and output it in a structured format.
It’s worth noting that the Yahoo Finance page heavily relies on JavaScript and features certain anti-scraping and data protection mechanisms. If you’re looking to continuously obtain structured financial data with greater stability and lower maintenance costs, you might consider using the dedicated Yahoo Finance Scraper API. This API handles details such as CAPTCHA recognition, fingerprinting, and automatic retries in a unified manner, making data collection smoother and more efficient.
Frequently asked questions
Is it illegal or against the rules to use Python to scrape Yahoo Finance?
Whether or not you’re allowed to proceed depends on the laws in your region, the site’s terms of service, its robots.txt policy, as well as the scale and purpose of your web scraping activities. We recommend reviewing the terms before going live and carefully controlling your access frequency. For large-scale commercial use, we strongly advise prioritizing authorized data sources or paid APIs.
Why does the script occasionally return empty data or throw errors?
Common causes: network fluctuations, temporary traffic throttling, invalid tickers, changes to interface fields, or being identified as abnormal traffic. Solutions:
●Add timeout and retry backoff.
●Reduce the crawling frequency and add caching.
●Record the original response snippet and status code for easy troubleshooting.
What should I do if HTML parsing can't extract the price?
Many page data are dynamically rendered on the front end, so the HTML source code may not include the final price. We recommend switching to a structured JSON interface or using the browser’s Network panel to identify the actual data requests.
About the author
Xyla is a technical writer who turns complex networking and data topics into practical, easy-to-follow guides, treating content like troubleshooting: start from real scenarios, validate with data, and explain the “why” behind each solution. Outside of work, she’s a Level 2 badminton referee and marathon trainee—finding her best ideas between the court and the finish line.
The thordata Blog offers all its content in its original form and solely for informational intent. We do not offer any guarantees regarding the information found on the Thordata blog or any external sites that it may direct you to. It is essential that you seek legal counsel and thoroughly examine the specific terms of service of any website before engaging in any scraping endeavors or obtain a scraping permit if required.
Looking for
Top-Tier Residential Proxies?
您在寻找顶级高质量的住宅代理吗?
How to Scraping Dynamic Websites with Python?
In this article, learn how to ...
Anna Stankevičiūtė
2026-03-03
TCP Deep Dive with Wireshark
Xyla Huxley Last updated on 2026-03-03 6 min read TCP i […]
Unknown
2026-03-03
Web Scraping with Python using Requests
Xyla Huxley Last updated on 2026-03-03 6 min read Web c […]
Unknown
2026-03-03
Web Scraping eCommerce Websites with Python: Step-by-Step Guide & Enterprise Alternatives
<–!> <–!> Anna Stankevičiūtė La […]
Unknown
2026-03-03
What Is AI Scraping? Definition, Technology, Applications, and Enterprise-Level Selection Guide
<–!> <–!> Anna Stankevičiūtė La […]
Unknown
2026-03-03
Concurrency vs Parallelism: Core Differences, Application Scenarios, and Practical Guide
<–!> <–!> Anna Stankevičiūtė La […]
Unknown
2026-03-03
Crawl4AI: Open-Source AI Web Crawler with MCP Automation
Xyla Huxley Last updated on 2026-03-03 10 min read AI a […]
Unknown
2026-03-03
Using Wget with Python: A Practical Guide for Reliable, Scalable Web Data Retrieval
Xyla Huxley Last updated on 2026-03-03 10 min read […]
Unknown
2026-03-03
What is a Python Proxy Server? A Complete Guide from Definition to Build
<–!> <–!> Anna Stankevičiūtė La […]
Unknown
2026-03-03