Collectors · Finance & crypto
MarketWatch API in Python
Live quote per ticker from MarketWatch — price, change, day and 52-week range, volume, market cap, P/E and EPS. One POST from Python with tickers, rows back as JSON with 31 fields, $0.003 per delivered quote. No proxies or parsers to maintain.

First call
Install, call, read the rows.
pip install requestsimport os, requests
r = requests.post(
"https://api.quanticdata.io/v1/scraper/collectors/marketwatch_quote/run",
headers={"Authorization": f"Bearer {os.environ['QD_API_KEY']}"},
json={
"tickers": ["AAPL"],
"max_results": 1,
},
timeout=120,
)
r.raise_for_status()
run = r.json()["payload"]
print(run["count"], "rows,", run["cost"]["usd"], "USD")
for row in run["results"]:
print(row.get("ticker"), row.get("requested_ticker"), row.get("name"), row.get("exchange"))The key comes from an environment variable, never from the code. The run answers in the same request when it finishes in time; payload.results holds the rows and payload.cost what they cost.
Request parameters
What the collector takes.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
tickers | array | yes | US-listed ticker symbols as MarketWatch spells them, e.g. AAPL, MSFT, BRK.B. |
country | string | no | ISO 3166-1 alpha-2 code — proxy exit geo and Google locale (gl). Omit for the default pool. |
max_results | integer | no (default 10) | How many quotes to deliver at most (1–25). You pay only for delivered quotes. |
Response fields
31 fields per quote.
| Field | Type | What it holds |
|---|---|---|
rank | integer | 1-based position in the delivered rows. |
ticker | string | Ticker symbol as the quote page states it. |
requested_ticker | string | The symbol you asked for — differs from `ticker` when MarketWatch resolved it to another listing. |
name | string, nullable | Company name. |
exchange | string, nullable | Listing exchange, e.g. "U.S.: Nasdaq". |
exchange_iso | string, nullable | ISO 10383 MIC, e.g. XNAS. |
currency | string, nullable | Price currency. |
instrument_type | string, nullable | Instrument type as MarketWatch classifies it, e.g. Stock. |
instrument_id | string, nullable | MarketWatch's internal instrument id. Stable across ticker changes; the key rows are de-duplicated on. |
price | number, nullable | Latest printed price as of `quote_time`, not as of the request — the page is CDN-cached. In premarket or after hours this is the extended-hours print, not the last regular close; `session` says which. |
change | number, nullable | Change against the previous close, in price terms. |
change_percent | number, nullable | Change against the previous close, in percent (0.45 means +0.45%). |
session | string, nullable | Which tape `price` came off: open, premarket, after_hours or closed. |
quote_time | string, nullable | As-of timestamp exactly as MarketWatch states it, including its exchange timezone, e.g. "Sep 2, 2026 8:20 a.m. EDT". This is how fresh the row actually is. |
previous_close | number, nullable | Previous regular-session close, read from the close table MarketWatch renders alongside an extended-hours quote. Null when the page does not carry that table. |
open | number, nullable | Regular-session open. In premarket or after hours this is the LAST COMPLETED session's open, the same tape as `volume` — not the session `price` came off. |
day_low | number, nullable | Regular-session low, at the page's full precision. In extended hours it belongs to the last completed session, so it is not a bound on `price`. |
day_high | number, nullable | Regular-session high, at the page's full precision. In extended hours it belongs to the last completed session, so it is not a bound on `price`. |
week52_low | number, nullable | 52-week low, at the page's full precision. |
week52_high | number, nullable | 52-week high, at the page's full precision. |
volume | integer, nullable | Regular-session volume. Not the extended-hours tape MarketWatch shows as "Before/After Hours Volume". |
avg_volume_65d | integer, nullable | 65-day average volume. |
market_cap | number, nullable | Market capitalisation, suffix expanded ($4.75T becomes 4750000000000). |
pe_ratio | number, nullable | Price/earnings ratio. Null when MarketWatch prints N/A, which it does for loss-making companies. |
eps | number, nullable | Earnings per share. Negative for loss-making companies. |
shares_outstanding | number, nullable | Shares outstanding, suffix expanded. |
public_float | number, nullable | Public float, suffix expanded. |
beta | number, nullable | Beta. |
dividend | number, nullable | Dividend per share as most recently declared. |
dividend_yield_percent | number, nullable | Dividend yield in percent (0.33 means 0.33%). |
url | string | Quote page the row was read from. |
Add ?format=csv to the runs endpoint to get the same rows as CSV.
Long runs
Run in the background, then poll.
A run that needs more time can go to the background: send "async": true, get 202 with the run id, and poll the runs endpoint until the status is done. Reading a run is free.
import os, time, requests
H = {"Authorization": f"Bearer {os.environ['QD_API_KEY']}"}
r = requests.post("https://api.quanticdata.io/v1/scraper/collectors/marketwatch_quote/run", headers=H,
json={**{"tickers":["AAPL"],"max_results":1}, "async": True}, timeout=30)
run_id = r.json()["payload"]["run_id"]
while True:
run = requests.get(f"https://api.quanticdata.io/v1/scraper/collectors/runs/{run_id}", headers=H, timeout=30).json()["payload"]
if run["status"] in ("done", "failed"):
break
time.sleep(5)
print(run["status"], run["count"])Errors
What can come back, and what is billed.
| Status | Meaning | Billed |
|---|---|---|
400 | The input does not match the collector (payload.errors) | No |
401 | Missing or wrong API key | No |
402 | Balance and free credit do not cover the run: top up | No |
422 | The input can never resolve; retrying the same input cannot help | No |
424 | The run failed at the source (blocked, timed out, layout changed); safe to retry | No |
429 | Rate limit or a per-account brake; wait for Retry-After | No |
Only delivered rows are billed: a run that delivers nothing costs nothing.
Price
$0.003 per delivered quote.
| Rows | Cost |
|---|---|
| 1 | $0.003 |
| 1,000 | $3.00 |
| 10,000 | $30.00 |
Up to 25 quotes per run; split larger jobs into several runs. The $2 free credit every month covers about 666 quotes. No subscription; paid tiers lower the unit price. All collector prices: collector pricing.
Before you run it
Questions developers ask
Is there a free MarketWatch stock quote API?
Every account gets $2 of free usage each month, about 666 quotes of this collector at $0.003 each, with no card.
Do I have to handle proxies, retries or blocks?
No. The collector runs on our network and handles them; a run blocked at the source returns 424 and is not billed.
How many rows can one run return?
Up to 25 quotes per run (the max_results input, where the collector has one).
Can an AI agent run it?
Yes: the MCP server exposes it as the run_collector tool, with the same input and price. See the MCP server.
Run it on the free credit.
Create an API key, export it as QD_API_KEY and run the example. $0.003 per delivered quote, no subscription.