For developers
Korean market data, in English, as JSON
Twenty years of Korean broker target prices and ratings — 66,105 records, normalised — plus the customs and classification series. The same data that goes into our reporting, available directly. No XML, no Korean-only field names.
Twenty years of Korean broker calls, in English
Every target price and investment rating issued by a Korean brokerage that we have collected: 66,105 records from December 2007 to last week, across 44research houses and 2,785 companies. Who said what, about which stock, on which day, and at what price.
This series does not exist in English anywhere else. Korean brokerages publish in Korean, rename themselves often, and each writes ratings its own way — we found 22 distinct spellings of eight actual levels, including one typo and one truncation that have been in the record for years. Normalising that is not a translation job; it is twenty years of bookkeeping.
Three normalisations come with every record, added beside the raw value, never replacing it:
brokerEntity— a stable id per legal entity. One firm appears under up to four Korean names in this archive: 이트레이드증권 became 이베스트투자증권 in 2015 and LS증권 in 2024. Counted separately it ranked 7th with 3,674 reports; grouped correctly it has 5,965. Any ranking that misses this is simply wrong.ratingNormalised— 22 source spellings folded into 8 levels.Outperformis deliberately not collapsed intoBuy; in Korea it sits one notch below, and merging them would erase the distinction analysts meant to draw.subjectEn— the company's own English spelling, which cannot be derived by rule (SK hynix, NCSOFT, AMOREPACIFIC). 2415 names cover 97.9% of records. The rest returnnullrather than a transliteration we invented.
One number to show what the archive is for: of the 55,560 rated reports,94.1% are positive and 0.16% negative — 89 negative calls in twenty years. That is not a claim we are making about Korean equity research. It is a count.
A request and its response:
curl "https://seoulmarkets.com/v1/research?broker=Mirae%20Asset&limit=1"{
"count": 1,
"results": [
{
"date": "2026-07-31",
"broker": "미래에셋증권",
"brokerEn": "Mirae Asset Securities",
"brokerEntity": "mirae-asset",
"brokerType": "brokerage",
"subject": "해성디에스",
"subjectEn": "Haesung DS",
"targetPrice": 80000,
"rating": "매수",
"ratingNormalised": {
"code": "buy",
"label": "Buy",
"score": 5,
"stance": "positive",
"raw": "매수"
},
"analyst": null,
"detailFetched": true,
"source": {
"agency": "Naver Finance (aggregator)",
"note": "Facts only. Report text and PDF are not collected."
}
}
],
"coverage": {
"total_records": 66105,
"first_day": "2007-12-03",
"latest_day": "2026-08-03",
"brokers": 44,
"subjects": 2785,
"as_of": "2026-08-03 19:19:19 KST"
}
}broker accepts the Korean name, the English name or the entity id, and a match returns every historical name of that entity — asking for Mirae Asset also returns its Daewoo Securities-era reports.
We collect facts, not documents. Report text, PDFs and charts are never fetched, so there is nothing copyrighted to redistribute. What a broker publicly stated its target price to be is a fact about the market.
Coverage is uneven by house, and you should know that before you build. Counted per firm, several of Korea's largest desks are barely present — Samsung Securities 381 records, Korea Investment 179, KB 27, NH 10. That is not their publishing volume; it is what our aggregation source carries. This archive is what one aggregator lists, not the full output of Korean research. If a house looks absent from the market, check it against this archive's per-house counts first. We are working to receive reports directly from research desks, which is the only thing that closes the gap — scraping harder cannot, because what is not there is not there.
Two more things we would rather tell you than have you discover: the archive is sparse before 2014 — 11 records in 2007, then a gap through 2013, dense from 2014 onward. And targetPrice is null for 4,164 records because credit-rating and IR bodies publish analysis without one; brokerTypetells you which is which, so you never mistake a structural absence for a gap in our collection.
Why the trade data too
Korea publishes monthly trade figures the day after the month ends, and provisional figures three times a month. Almost no country moves that fast: UN Comtrade runs up to a month behind, and further for many reporters. Bloomberg counts Korean trade among its twelve key global economic indicators for exactly this reason — Korea imports raw materials, processes them and re-exports, so a shift in world demand shows up here first.
That much is well known. What does not exist is the detail in a usable form. The headline number gets reported; the product-level series does not. Korean official feeds return XML, with product and country names in Korean, and no English classification attached. This API is that missing layer.
Available now
These endpoints are live and need no key. The research archive is the data we collected; the classification endpoints resolve the part that normally costs a translator.
| Endpoint | What it does | Try it |
|---|---|---|
/v1/research | Every target price and rating issued by Korean brokerages, 2007-2026. 66,105 records. | run |
/v1/institutions | The 44 Korean research houses in English, grouped into 34 legal entities across renames. | run |
/v1/hs/{code} | Resolve any HS code — 2, 4, 6 or 10 digits — to its English description. | run |
/v1/hs?q={keyword} | Search the classification in English when you do not know the code. | run |
/v1/countries | Partner country codes with English names. | run |
/v1/meta | Coverage, dictionary size, and exactly what has been collected so far. | run |
A request and its response:
curl https://seoulmarkets.com/v1/hs/8542{
"code": "8542",
"digits": 4,
"chapter": {
"code": "85",
"name": "Electrical machinery and equipment and parts thereof"
},
"heading": {
"code": "8542",
"name": "Electronic integrated circuits"
},
"label": "Electronic integrated circuits",
"resolved": true,
"source": {
"agency": "World Customs Organization",
"system": "Harmonized System"
}
}Opening next
These return 404 today with a machine-readable reason in the body. They open as soon as collection starts — we would rather say so than hand you an empty array that looks like a real answer. A filter that legitimately matches nothing returns200 with count: 0; the two are different answers and we keep them different.
| Endpoint | What it will return |
|---|---|
/v1/trade/flash | Korea's 10-day provisional trade figures, by product. Released 1st, 11th and 21st at 09:00 KST. |
/v1/trade/exports | Exports and imports by HS code and partner country, monthly, back to the start of our archive. |
Clients
Two thin clients, single files, in this site's repository underclients/. They are not on npm or PyPI yet — copy the file rather than installing a package. We would rather say that than publish an install command that fails.
// clients/js/seoulmarkets.mjs — copy the file, no install needed
import { Client } from './seoulmarkets.mjs';
const sm = new Client();
const chip = await sm.hs('8542');
console.log(chip.label); // Electronic integrated circuits
console.log(chip.resolved); // true
await sm.search('battery'); // 8506, 8507# clients/python/seoulmarkets.py — pip install requests, then copy the file
from seoulmarkets import Client
sm = Client()
print(sm.hs("8542").label) # Electronic integrated circuits
print(sm.search("battery")) # [8506, 8507]The JavaScript client has no dependencies at all — it uses the built-infetch, so it runs unchanged on Node 18+, Deno, Bun, Cloudflare Workers and in the browser. The Python client needs only requests.
Both surface the resolved flag rather than hiding it, and both raise a typed error carrying the server's own reason code — so your code can tell not collected yet apart from no trade occurred. That distinction is the whole reason these clients read the error envelope instead of the status line.
The same question always gets the same answer
This sounds obvious until you try to build on a source that does not guarantee it. Korean agencies revise: a 10-day provisional figure is superseded by the monthly final, and the monthly final is itself revised around the 15th of the following month.
We keep the revisions alongside the originals rather than overwriting them. If you pulled a number in March and pull it again in September, you can retrieve exactly what March returned, and see what changed since. Backtests that silently rewrite their own history are not backtests.
Field names are part of the contract, not an implementation detail. Within v1we may add fields; we do not remove or rename them. A breaking change ships as/v2 with both running. The policy is published at /v1/meta so you do not have to take our word for it.
How we handle what we do not know
Our heading dictionary covers the products that dominate Korean trade. A code outside that set resolves to its chapter and returns null for the heading, with a note saying so. We do not generate a plausible description to fill the gap. A data product that guesses is worse than one with holes, because you cannot tell which is which.
Every response names its source. Where a figure is provisional, it is labelled provisional, and the revision is kept alongside rather than overwriting it.
Licence
Trade, classification and macro series. Published by Korean government agencies under an unrestricted-use licence, which permits redistribution including for commercial purposes. We do not redistribute exchange feeds or licensed vendor data.
The research archive is a different matter, so we will be precise about it. A brokerage report is a copyrighted work. What we hold is not the report: it is the set of facts the broker stated publicly — which house, which analyst, which company, which date, what target price, what rating. We do not collect report text, tables, charts or PDFs, so there is nothing of the work itself here to redistribute. Aggregating published target prices is what financial media have always done; reproducing the analysis is not, and we do neither by construction rather than by policy.
If you need the reports themselves, we cannot sell them to you and will say so rather than take the order.
Pricing
The classification endpoints above are free and will stay free. The research archive is open now with a free tier generous enough to build and backtest against; paid tiers cover production volume and bulk history export. Trade series price the same way when they open. Institutional licences — full archive, custom aggregations, delivery to your warehouse — are contracted directly.
No key is required to call this API directly, and that does not change. The limits below are published now and take effect on 2026-08-17 — until then every response carries your current usage in X-RateLimit-* headers and nothing is ever rejected, so you can size your integration before anything binds.
| Records per request | Requests per minute | |
|---|---|---|
| Direct, no key | 200 | 60 per IP |
| Through a marketplace plan | 1000 | set by your plan |
The whole archive is 66,105 records. At 200 per call that is 331 requests; at 1000 it is 67. That difference is what the paid plans are for — not access to different data. Every field is in the free response too.
Tell us what you need and we will tell you plainly whether we have it: sibcheongan@gmail.com.
Who we are
SeoulMarkets is published by KLifeDesign InC., registered in Korea. The API and the newsroom run on the same pipeline — every figure in an article comes from the endpoints above, which is why both stay honest. More in About.