Fetch Financial Data from Naver Finance
Purpose
Pull structured financial data for any Korean-listed equity (KOSPI/KOSDAQ) — and Naver-tracked world stocks, indices, and crypto — from Naver Finance's undocumented public JSON APIs instead of scraping the JS-rendered HTML pages. Returns compact JSON (current quote, OHLCV, market cap, PER/EPS/PBR/BPS, dividend, 52-week range, annual/quarterly financial statements, price history) so an LLM can consume it with minimal tokens. Read-only; no auth, no cookies, no anti-bot stealth, and no residential proxy required.
When to Use
- "What's the current price / market cap / PER of 삼성전자 (Samsung, 005930)?"
- Resolving a Korean company name to its 6-digit ticker code.
- Pulling daily OHLCV history for charting/backtesting.
- Reading a company's annual or quarterly income-statement rows (매출액/영업이익/순이익 etc.).
- Checking the live KOSPI / KOSDAQ index level.
- Any LLM-driven workflow that needs a terminal/CLI-style, low-token data pull from Naver Finance — prefer this over rendering
finance.naver.comHTML, which is heavy and JS-gated.
Workflow
Naver's web/mobile front-ends are thin clients over a public JSON API on the m.stock.naver.com, polling.finance.naver.com, and ac.stock.naver.com hosts. No API key, cookie, session, stealth, or proxy is needed — a plain HTTPS GET works (verified bare, with browse cloud fetch over the residential-proxy path, and via a non-stealth Browserbase session). Lead with these endpoints; only fall back to the browser if an endpoint is ever rate-limited.
All requests are plain GETs. From this CLI, use browse cloud fetch "<url>" (it returns a JSON envelope — the body is in the .content field as a JSON string you parse again). curl/fetch against the same URLs works identically.
1. Resolve a ticker from a company name (autocomplete)
GET https://m.stock.naver.com/front-api/search/autoComplete?query={URL-enc name}&target=stock,index,marketindicator,coin,ipo
Returns result.items[], each with code (the 6-digit ticker for domestic stocks), name, typeName (코스피/코스닥), reutersCode, and url (/domestic/stock/{code}/total). Take items[0].code as the best match. The query may be Korean or English. (A legacy equivalent lives at https://ac.stock.naver.com/ac?q={name}&target=stock,index,marketindicator,coin,ipo&st=111.)
2. Realtime / latest quote (compact — fewest tokens)
GET https://polling.finance.naver.com/api/realtime/domestic/stock/{code}
Returns datas[0] with closePrice (current/last price), compareToPreviousClosePrice (change), fluctuationsRatio (% change), openPrice, highPrice, lowPrice, accumulatedTradingVolume, accumulatedTradingValue, marketStatus (OPEN/CLOSE), localTradedAt (ISO+09:00), and overMarketPriceInfo (pre/after-market). Pass multiple codes comma-separated (.../stock/005930,000660,035720) to batch several tickers in one round-trip. This is the cheapest endpoint for "just the price."
3. Rich snapshot (valuation metrics in one call)
GET https://m.stock.naver.com/api/stock/{code}/integration
Returns totalInfos[], a flat array of {code, key, value} rows. Observed codes: lastClosePrice (전일), openPrice, highPrice, lowPrice, accumulatedTradingVolume (거래량), accumulatedTradingValue (대금), marketValue (시총), foreignRate (외인소진율), highPriceOf52Weeks/lowPriceOf52Weeks (52주 최고/최저), per, eps, cnsPer/cnsEps (추정/forward), pbr, bps, dividendYieldRatio (배당수익률), dividend (주당배당금). Also includes industryCompareInfo, consensusInfo, and researches. A lighter version is /api/stock/{code}/basic (price + exchange metadata only).
4. Financial statements
GET https://m.stock.naver.com/api/stock/{code}/finance/annual
GET https://m.stock.naver.com/api/stock/{code}/finance/quarter
Returns financeInfo.trTitleList[] (period columns, e.g. {title:"2024.12.", key:"202412", isConsensus:"N"}) and financeInfo.rowList[] where each row is {title:"매출액", columns:{ "202412": {value:"3,008,709"}, ... }}. Units are 억원 (hundred-million KRW). isConsensus:"Y" marks forecast columns.
5. Price history (OHLCV)
GET https://m.stock.naver.com/api/stock/{code}/price?pageSize={N}&page=1
Returns a JSON array of daily bars: localTradedAt (YYYY-MM-DD), closePrice, compareToPreviousClosePrice, fluctuationsRatio, openPrice, highPrice, lowPrice, accumulatedTradingVolume. Page through with page.
6. Market index (KOSPI / KOSDAQ)
GET https://polling.finance.naver.com/api/realtime/domestic/index/{KOSPI|KOSDAQ}
Same shape as the stock realtime endpoint (closePrice = index level).
Browser fallback
If any JSON endpoint is ever rate-limited or returns an error page, open the mobile page in a non-stealth session and read the rendered values: browse open "https://m.stock.naver.com/domestic/stock/{code}/total" --remote, browse wait load, browse wait timeout 2500, then browse get text body. This costs far more tokens than the JSON path — use only as a last resort. (You can also browse open the JSON URLs directly and browse get text body, which is what an in-browser agent does.)
Site-Specific Gotchas
- Use the
m.stock.naver.com/api/...host, NOTapi.stock.naver.com. Directhttps://api.stock.naver.com/stock/{code}/integrationreturns409 {"code":"StockConflict"}(it expects internal auth/referer). Them.stock.naver.com/api/stock/{code}/...host serves the same data with no auth. - The search path is
front-api/search/autoComplete, notapi/search/all.https://m.stock.naver.com/api/search/all?...returns a404HTML error page. Usefront-api/search/autoComplete(orac.stock.naver.com/ac). - All numeric values are formatted strings, not numbers. Prices come as
"354,000"(comma thousands separators). Strip commas before arithmetic. Some fields carry Korean unit suffixes:백만= million KRW (accumulatedTradingValue),천주= thousand shares, and market cap uses조(trillion) +억(hundred-million), e.g."2,069조 5,826억". Statement rows are in 억원 (hundred-million KRW). - Direction is encoded in
compareToPreviousPrice.code:2= 상승 (RISING / up),5= 하락 (FALLING / down); unchanged/limit codes exist too.compareToPreviousClosePriceis already signed for stocks but read.codefor direction-safe logic. browse cloud fetchdouble-wraps the body. The envelope's.contentis the response body as a string;JSON.parseit again to get the data object.jqis not installed in this sandbox — parse withnode -e.pollingInterval(≈70000ms) is just the front-end's suggested refresh cadence, not a rate limit. There is no observed hard rate limit, but keep requests reasonable (≤ ~1/s sustained); no formal block was hit during testing.- Times are KST.
localTradedAtis ISO-8601 with+09:00.marketStatusisOPEN/CLOSE; outside trading hoursclosePriceis the last close andoverMarketPriceInfoholds pre/after-market prints. - Tickers are 6 characters (digits for common KOSPI/KOSDAQ stocks; some ETFs/ETNs include a letter, e.g.
0162Z0). World stocks use areutersCodelikeAAPL.Ounder/worldstock/...— this skill targets domestic equities. - All text is UTF-8 Korean. URL-encode Korean query terms; expect Korean labels in
keyfields. - No anti-bot, no proxy, no stealth. Pre-run probe of the homepage detected no anti-bot, and every endpoint above returned
200over a bare connection.verifiedandproxiesare bothfalse.
Expected Output
Compact quote + valuation snapshot (combining the realtime and integration endpoints):
{
"success": true,
"ticker": "005930",
"name": "삼성전자",
"market": "코스피",
"price": "354,000",
"change": "-8,500",
"change_pct": "-2.34",
"direction": "FALLING",
"open": "380,000",
"high": "380,000",
"low": "346,000",
"prev_close": "362,500",
"volume": "76,480,025",
"market_cap": "2,069조 5,826억",
"per": "28.61배",
"eps": "12,372원",
"pbr": "4.92배",
"bps": "71,907원",
"dividend_yield": "0.47%",
"high_52w": "380,000",
"low_52w": "57,600",
"foreign_rate": "47.62%",
"market_status": "CLOSE",
"traded_at": "2026-06-19T15:30:00+09:00",
"error_reasoning": null
}
Annual financial statements (/finance/annual):
{
"ticker": "005930",
"period_type": "annual",
"periods": [
{"title": "2023.12.", "key": "202312", "is_forecast": false},
{"title": "2024.12.", "key": "202412", "is_forecast": false},
{"title": "2026.12.", "key": "202612", "is_forecast": true}
],
"rows": [
{"title": "매출액", "values": {"202312": "2,589,355", "202412": "3,008,709"}},
{"title": "영업이익", "values": {"202312": "65,670", "202412": "327,260"}}
],
"units": "억원"
}
Ticker resolution (autocomplete):
{
"query": "삼성전자",
"matches": [
{"code": "005930", "name": "삼성전자", "market": "코스피", "url": "/domestic/stock/005930/total"}
]
}
Failure (unknown ticker / endpoint error):
{ "success": false, "error_reasoning": "No autoComplete match for query; or endpoint returned non-200." }