FMKorea Scraper API

FMKorea answers plain HTTP clients with a block page. This Actor runs a real browser behind residential proxies and returns board posts — title, author, date, comment count, notice flag — as a dataset.

FMKorea blocks bots. That's why this one pays for proxies.

If you have tried to read FMKorea from a script, you already know the ending: a security-system page instead of a board. Datacenter IPs get filtered, plain HTTP clients get challenged, and the board you wanted never loads.

So this Actor makes the trade openly. It runs on Apify residential proxies by default, because on this site a cheap datacenter run returns a block page and costs you time instead of money. Residential traffic costs more per gigabyte than datacenter traffic, and pretending otherwise would be the dishonest version of this page.

What the wall actually is

The page FMKorea hands back is not a checkbox you can click and not a cookie you can forge. It loads a WASM module from /mc/mc.php, computes a proof, posts a form back to the server, and reloads itself with ddosCheckOnly=1. Cloudflare Turnstile sits behind that. Each response carries its own token, so a value copied out of one page is worthless on the next.

Which is why this Actor does not parse HTML fetched with a plain HTTP client. It opens the board in Chromium, lets the page run its own scripts the way a reader's browser would, waits until real listing links have replaced the challenge, and only then reads rows. If a proxy session keeps getting walled, the Actor retires it and retries on a fresh residential IP, up to eight attempts per board.

The other half of that problem is silence. A 430 block page is not an error status as far as a crawler is concerned, so the naive version of this scraper used to finish "successfully" with zero rows. This one checks for the wall explicitly and fails with a readable message instead, because a run that quietly returns nothing is worse than a run that tells you why.

What you get back

FMKorea is Korea's largest community forum — sports boards, news, humor, and long threads that matter to Korean readers. The list pages on those boards are dense with structured information once you can actually reach them:

  • docId — the stable document id
  • title and absolute url
  • author — display name
  • timeText — the date exactly as the board shows it
  • comments — comment count, when the board displays one
  • isNotice — whether the post is a pinned board notice

isNotice exists because notice posts otherwise pollute every trend you compute. A board with four pinned notices per page is 40% noise at ten rows per page. Pinned notices repeat on every page of a board, so they are counted once per run, and the advertising banners pinned above them — bare links with no author and no timestamp — are dropped before they reach your dataset.

Point it at a board URL — https://www.fmkorea.com/index.php?mid=baseball, or a single-segment alias like https://www.fmkorea.com/news. A &page=N start value is honoured, and maxItems caps posts per start URL.

Three jobs it fits

  1. Community monitoring. Follow a board or a set of boards and diff new posts between runs. Which topics appeared, which ones took off.
  2. Trend research. Posting volume and comment counts over time, per board, with notices filtered out.
  3. Content datasets. Titles, authors and timestamps for Korean-language corpora, without mirroring full post bodies.

What it will not do

It reads public board listings. No private boards, no DMs, no member profiles, and no post bodies beyond what the listing shows. Comment counts are captured as displayed — it does not open every thread to count them.

Two practical notes. Start with a specific board rather than the site root, because the root page is a mix of everything and diffs badly. And because a browser session plus residential bandwidth is the real cost, run one board at a time and keep maxItems at what you actually need.

Run it

Run FMKorea Scraper on Apify.

  1. Paste board URLs (page numbers optional).
  2. Set how many posts per board you want.
  3. Leave the proxy setting at its residential default.
  4. Export JSON, CSV or Excel, or schedule it and diff.

Pricing is pay-per-event on posts returned, so a blocked run does not charge you per item — but the browser and residential session still cost something, which is why the defaults are tuned for one board at a time rather than a mass crawl.

For the same shape of problem on a site that does not fight back, see how we summarise Reddit comment threads, and for the general "public page to dataset" pattern, price extraction.