Files
mangabaka-seeder/docs/specs/004-kakaopage.md
T

4.1 KiB
Raw Blame History

status
status
approved

004 — KakaoPage source

A third source (spec 001 §4.1): covers of a KakaoPage series, comics (웹툰) and novels (웹소설). Design approved by the user in chat on 2026-10-15. Kakao Webtoon (webtoon.kakao.com) is a different site and out of scope.

1. Verified facts (2026-10-15)

Checked against 악역의 엔딩은 죽음뿐 (Villains Are Destined to Die; comic 54845189, novel 52654302) and 울프 인더 하우스 [19세 완전판] (63659962, 19+). Fixtures in test/fixtures/kakaopage/ and test/fixtures/wayback/kakaopage-*.

  • Pages are rendered in the browser. page.kakao.com/content/<id> is an 11 KB shell with a generic og:image; the data comes from GET https://bff-page.kakao.com/api/gateway/api/v1/content/overview?series_id=<id>.
  • That endpoint needs a page.kakao.com Referer (or Origin); without one it answers 403. It answers 19+ series without a login.
  • Its result.content: series_id, title, category (웹툰 / 웹소설), age_grade (0, 12, 15, 19), lang (ko), thumbnail (portrait key, e.g. 720×1030), land_thumbnail (landscape key, 540×370; may be null). An unknown id answers with an error (상품 정보를 찾을 수 없습니다, "product not found").
  • Images: https://page-images.kakaoentcdn.com/download/resource?kid=<key>&filename=o1 is the original (th2, th3 and /dims/resize/… are smaller). No Referer needed. Older pages use dn-img-page.kakao.com with the same query; old keys answer on the new host.
  • Wayback: page.kakao.com/home?seriesId=<id> (the old address, 2020–2022) and page.kakao.com/content/<id> (2022 on) are captured server-rendered. Every capture's og:image is this series' image (landscape in 2020–22, portrait in 2024). 2020 captures also hold props.initialState.series.series.thumbnailUrl and landThumbnailUrl in __NEXT_DATA__. Other images on the page (sameSeriesList, comments) are other series or users.

2. Behaviour

  • Links: page.kakao.com/content/<id> (with or without a trailing path/query) and page.kakao.com/home?seriesId=<id>; m. hosts too.
  • Series: from the overview endpoint: externalId = id, title, language = lang (ko), canonicalUrl = https://page.kakao.com/content/<id>, mature = age_grade >= 15 (the rating warning), flags.novel, archiveUrls = [page.kakao.com/content/<id>, page.kakao.com/home?seriesId=<id>].
  • Current covers: thumbnail → role poster (the suggested main cover), land_thumbnail → role banner.
  • History: from a capture: og:image (role other: portrait or landscape, the shape decides the type) and, when present, the series' own thumbnailUrl (poster) and landThumbnailUrl (banner).
  • Same series: a link is the same series when its id (/content/<id> or seriesId=<id>) equals ours exactly, so seriesId=548451890 is another series.
  • Image URLs: both hosts → page-images.kakaoentcdn.com, filename=o1, the kid kept, any /dims/… dropped.
  • Request headers per host: requestHeadersFor(url) in core/transport.ts (User-Agent as before, plus Referer: https://page.kakao.com/ for bff-page.kakao.com). The server proxy and the userscript send them.
  • Hosts: fetch page.kakao.com, m.page.kakao.com, bff-page.kakao.com, page-images.kakaoentcdn.com, dn-img-page.kakao.com; images the last two. The userscript @connects kakao.com and kakaoentcdn.com.
  • Chrome: the link hint names "WEBTOON, Tapas or KakaoPage".

3. Testing

Offline unit tests on the captures: link parsing, URL normalisation, same-series, overview parsing (comic, novel, 19+, unknown id), archived pages (2020, 2022, 2024), Wayback rows through both prefixes, request headers. Then a real run in headless Chrome (current covers, then yearly history).

4. Risks

  • The overview endpoint is an internal API: its shape or its Referer check can change.
  • Sending a page.kakao.com Referer is what KakaoPage's own page sends; like the browser User-Agent for Webtoons, it is a browser-like header, not an identity.