# Naver News Search Scraper - Press Monitoring, Day by Day (`mochiboo/naver-news-search-scraper`) Actor

Search Naver News (네이버 뉴스) by keyword: one row per article with headline, press, age, snippet and links, day by day over a date range, related articles in relevance mode, and exact time, sections and full text for articles Naver News hosts, with no login or API key.

- **URL**: https://apify.com/mochiboo/naver-news-search-scraper.md
- **Developed by:** [mochi](https://apify.com/mochiboo) (community)
- **Categories:** News, Marketing, Automation
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Naver News Search Scraper - monitor Korean press coverage by keyword, day by day

Search **Naver News (네이버 뉴스)**, Korea's main news portal, for any keyword and get one row per article: headline, press, age, snippet, thumbnail, the press's own link and the Naver News link. Give a **date range** and the actor walks it day by day, newest first, for press monitoring. Switch to **relevance** and Naver's related articles from other presses come as rows too, so coverage per story is one group-by away. Switch on **Open each article** to add the exact publish and update time, the sections and the full text.

It reads the same public pages anyone sees in a browser, in Korea's own news search and on the article page itself. **No Naver account, no API key, no login, no cookies.**

### Read this first

- **Naver's public search page shows 10 stories per page and has no second page.** Without dates you get the 10 newest articles (`sortBy` `newest`) or the 10 most relevant stories with the related articles Naver lists under each (`relevance`: 10 rows for a keyword without related coverage and up to 50 for a busy one; 22 to 30 rows for the three busy keywords we ran on 2026-10-31 and 2026-11-01). With a date range the actor asks once per Korea-time day and returns the 10 newest articles of that day. A busy keyword is therefore **sampled, not complete**: for `스타벅스` on 2026-10-30 the 10 articles of the day were written between 19:00 and 23:38 Korea time, the last hours of that day. A quiet keyword, with fewer than 10 articles a day, returns every article Naver lists for that day; a day without an article gives no row and the run summary counts it in `emptyDays`.
- **`publishedTimeText` is Naver's own text**, a relative text (`48분 전`, `11시간 전`, `1일 전`, `3주 전`), a date (`2026.07.15.`) or the print-edition position of the article (`A23면 1단`). The **exact time** (`publishedAt`, UTC) comes with **Open each article**.
- **Only articles that Naver News hosts have a Naver News link and can be opened.** On the newest-first pages we read on 2026-11-01 this was 0 to 9 of 10 articles, 3.7 on average over 29 pages, and in relevance mode about 9 of 10 stories (the other articles are only on the press's own site: their `naverNewsUrl` is `null` and, with Open each article on, their `contentState` is `notOnNaver`; they cost no extra request). The press's own link (`articleUrl`) is always there.
- **Open each article costs one more request per article** and the actor waits 2.5 seconds between any two requests, so a page of 10 articles with their full text takes up to about 30 seconds. Without it a search page takes a few seconds. A very large run (many keywords and days) may stop early at the run's time limit: it then keeps every row it already delivered and says `time_budget` in the run summary. Nothing is lost silently.
- **Some Naver-hosted articles cannot be read as articles.** Entertainment and sports articles that Naver moves to its own entertainment or sports sites answer with a redirect (the actor never follows it) or with a page of another layout: they keep their search row, with `contentState` `unavailable` and empty article fields. The same holds for an article Naver has deleted. Such a row is still delivered and counted; the run summary counts them in `contentUnavailable` (and the redirects among them in `articleRedirects`).
- **E-mail addresses in snippets, headlines and article text, and phone numbers in snippets and article text, are replaced (best effort)** with `[email redacted]` and `[phone redacted]`: addresses in common spellings (also `name (at) host.com` and Korean `name골뱅이host.com`) and Korean mobile and landline formats (`010-1234-5678`, `02-398-8585`, `+82 10 ...`), also when several numbers stand side by side. Some articles end with a reporter's or desk address or phone line (in our test runs 2 of 14 articles held an address on 2026-10-31, one of them also a phone number, and 6 of 26 on 2026-11-01); it comes out as `[email redacted]` or `[phone redacted]`. Unusual spellings can slip through.
- **A refusal from Naver ends the run.** If Naver answers a search page with 403, 429, a redirect or a page that is not the news search page, or answers an article page with 403, 429 or another unexpected status, the actor stops, keeps every row it already collected and says `blocked` in the run summary. It does not retry, rotate or disguise itself.
- Not covered: comments, reactions, the article's images, the other Naver tabs (blog, cafe, shopping), articles beyond the 10 per keyword and day that the page shows, and the full related-news list behind a story's "view all" link (the page lists up to 4 related articles under a story; the link behind it counted 37 for the top `스타벅스` story on 2026-10-30). Not affiliated with Naver.

### What you get

One row per article:

| field | meaning |
|---|---|
| `keyword`, `sortBy` | the keyword you searched and `newest` or `relevance` |
| `windowDate` | with a date range: the Korea-time day the row was found for (`2026-10-25`); otherwise `null` |
| `rank` | position of the row on that search page (1 = first) |
| `clusterRank`, `isRelated` | the story the row belongs to (1 = first story of the page) and whether it is a related article of that story (`true`) or the story's main article (`false`); related articles appear in `relevance` mode only |
| `title`, `snippet` | the headline and the excerpt Naver shows (search highlights removed, contact details replaced); `snippet` is `null` for related articles. Naver cuts long headlines and excerpts and marks the cut with `...` (about 1 headline in 4 in our runs on 2026-11-01) |
| `articleUrl` | the press's own link to the article |
| `naverNewsUrl` | the article's Naver News link (`https://n.news.naver.com/mnews/article/001/0016411348?sid=102`); `null` if Naver News does not host it |
| `pressName`, `pressOid`, `articleAid` | the press and, for Naver News links, the press number and article number (`001`, `0016411348`) |
| `publishedTimeText` | Naver's text for the age or date, for example `11시간 전` |
| `thumbnailUrl` | the article's picture on Naver's image server; `null` for related articles and articles without a picture |
| `contentState` | `null` when you did not ask for article pages; `ok` when the article page was read; `unavailable` when it could not be read; `notOnNaver` when Naver News does not host the article |
| `publishedAt`, `modifiedAt` | exact publish and update time, ISO UTC (`2026-10-30T02:07:34.000Z`); `modifiedAt` is `null` when the page shows no update time; with Open each article |
| `sections` | the sections the press filed the article under (`["사회","경제"]`) |
| `content`, `contentLength` | the full text, one paragraph per line, contact details replaced; its length in characters |
| `scrapedAt` | when the row was collected |

The key-value store also holds `RUN_SUMMARY`: `complete`, `terminationReason` (`finished`, `max_results`, `charge_limit`, `time_budget`, `blocked`, `request_failed`), `rowsPushed`, one entry per keyword (`pages`, `rows`, `emptyDays`, `contentUnavailable`, `articleRedirects`, `notOnNaver`), keywords left out beyond the first 50 (`skippedOverLimit`) and `warnings`. `complete` is `false` when the run ended before it could deliver what you asked for (`time_budget`, `charge_limit`, `blocked`, `request_failed`). If the platform restarts a run, `articleRedirects` can miss some redirects of the earlier part; every other number stays exact.

### Input

| field | default | meaning |
|---|---|---|
| `keywords` (required) | `스타벅스` | what to search for, one keyword or phrase per line, up to 50 per run (Korean or English); blanks and duplicates are dropped |
| `sortBy` | `newest` | `newest` (needed for date ranges) or `relevance` (10 stories with their related articles; dates are ignored) |
| `dateFrom`, `dateTo` | empty | `YYYY-MM-DD` in Korea time. With `newest`, every day from `dateTo` back to `dateFrom` is searched, newest day first. `dateTo` alone is refused; `dateFrom` alone ends today (Korea). At most 366 days. Leave both empty for the 10 newest articles. **The dates stay fixed in a saved input, so a schedule repeats them**: for yesterday's articles only, set the dates from your own scheduler or API call, or run without dates and drop repeats by `articleUrl` |
| `maxArticlesPerKeyword` | 100 | 1-5000 rows per keyword (the default stops after 10 days of a date range, so raise it for a longer range) |
| `includeArticleContent` | off | open each article hosted on Naver News: exact time, sections, full text |
| `proxyConfiguration` | Apify datacenter proxy | the default is what this actor was tested with |

Examples:

- The 10 newest articles about a brand: `{"keywords": ["스타벅스"]}`
- Three days, two keywords, 10 articles a day each: `{"keywords": ["스타벅스", "삼성전자"], "dateFrom": "2026-10-29", "dateTo": "2026-10-31"}` returns 60 rows.
- Coverage per story: `{"keywords": ["스타벅스"], "sortBy": "relevance"}` returned 22 rows (10 stories and 12 related articles) when we ran it on 2026-10-31; group by `clusterRank` to count the presses per story.
- The newest 10 articles with full text: `{"keywords": ["삼성전자"], "includeArticleContent": true, "maxArticlesPerKeyword": 10}`

### Example row

```json
{
  "keyword": "스타벅스",
  "sortBy": "relevance",
  "windowDate": null,
  "rank": 1,
  "clusterRank": 1,
  "isRelated": false,
  "title": "스타벅스, '탱크데이' 불매운동 후 광주 대형매장 첫 폐점",
  "articleUrl": "https://www.yna.co.kr/view/AKR20261030074300054?input=1195m",
  "naverNewsUrl": "https://n.news.naver.com/mnews/article/001/0016411348?sid=102",
  "pressName": "연합뉴스",
  "pressOid": "001",
  "articleAid": "0016411348",
  "publishedTimeText": "11시간 전",
  "snippet": "스타벅스코리아가 '탱크데이' 불매운동 후 처음으로 광주에서 대형 매장을 폐쇄했다. 30일 스타벅스코리아에 따르면 전남광주 동구 산수동 무등산국립공원 초입의 '스타벅스 광주지산유원지입구점'이 이날 문을 닫았다. 2017년 개점 이후 인근 거주 주민들은 물론 무등산 방문객 등도 많이 이용했던 지상...",
  "thumbnailUrl": "https://imgnews.pstatic.net/image/origin/001/2026/10/30/16411348.jpg",
  "contentState": "ok",
  "publishedAt": "2026-10-30T02:07:34.000Z",
  "modifiedAt": "2026-10-30T02:08:16.000Z",
  "sections": [
    "사회",
    "경제"
  ],
  "content": "'탱크데이' 파문에 깨지고 부서진 스타벅스 텀블러\n[연합뉴스 자료사진]\n(전남광주=연합뉴스) 정회성 기자 = 스타벅스코리아가 '탱크데이' 불매운동 후 처음으로 광주에서 대형 매장을 폐쇄했다.\n30일 스타벅스코리아에 따르면 전남광주 동구 산수동 무등산국립공원 초입의 '스타벅스 광주지산유원지입구점'이 이날 문을 닫았다.\n2017년 개점 이후 인근 거주 주민들은 물론 무등산 방문객 등도 많이 이용했던 지상 2층짜리 단독 상가건물의 대형매장으로 전날 영업을 끝으로 운영을 종료했다.\n스타벅스코리아는 상가 임대차 계약 종료로 해당 매장을 폐점한 것으로 알려졌다.\n스타벅스코리아는 5·18 46주년인 올해 5월 18일 텀블러 할인 행사에 1980년 5월 당시 계엄군의 무력 진압을 연상케 하는 '탱크데이' 표현을 사용해 물의를 빚으며 불매운동으로 번졌다.\n스타벅스는 5월부터 넉 달 연속 국내 커피브랜드 1위(신용·체크카드 추정 결제액 기준)를 다른 업체에 내줬고, 지난달 들어 추정 결제액 1천200억원대로 선두 자리를 되찾았다.\n[email redacted]",
  "contentLength": 534,
  "scrapedAt": "2026-10-30T13:44:55.000Z"
}
```

### Good to know

- **Press monitoring**: run `newest` with the previous day as `dateFrom` and `dateTo` once a day, with `maxArticlesPerKeyword` 10 (or more if you list several days), and join on `articleUrl`.
- **Coverage per story**: `relevance` shows what Naver ranks first for a phrase and which other presses ran the same story (`clusterRank`, `isRelated`).
- **Speed**: one request at a time, a 2.5 second pause between requests. Through the proxy plan about 3 seconds per request, search page or article page (runs on 2026-10-31 and 2026-11-01).
- **Cost control**: you pay per delivered row, so `maxArticlesPerKeyword` is also a cost cap. The platform's own spending limit stops the run (`charge_limit` in the summary) and keeps the rows already delivered.
- **Restarts**: if the platform moves the run to another server, the actor continues where it stopped and does not deliver (or charge) a row twice.

### Pricing

Pay per result, at the rate shown in the pricing panel of this page, plus a very small per-run start fee. You are charged only for the results delivered.

### Related searches

naver news scraper, naver news search, 네이버 뉴스 크롤링, 네이버 뉴스 검색, korean news monitoring, press monitoring korea, naver scraper

# Actor input Schema

## `keywords` (type: `array`):

What to search for on Naver News, one keyword or phrase per line (Korean or English). Up to 50 per run.

## `sortBy` (type: `string`):

Newest first (needed for date ranges; the 10 newest articles per day) or Naver's relevance ranking (10 stories with their related articles).

## `dateFrom` (type: `string`):

YYYY-MM-DD. With 'Newest first', the actor walks every day from 'To date' back to this date and returns the 10 newest articles per keyword per day. Leave both dates empty to get the 10 newest articles.

## `dateTo` (type: `string`):

YYYY-MM-DD. Defaults to today (Korea time) when only 'From date' is set.

## `maxArticlesPerKeyword` (type: `integer`):

1-5000. Naver shows 10 articles per keyword per day (10 in total without dates). With a date range the default of 100 stops after 10 days: raise it to read every day.

## `includeArticleContent` (type: `boolean`):

One extra page per article hosted on Naver News; about 2.5 seconds per article. Articles only on the press's own site are marked notOnNaver.

## `proxyConfiguration` (type: `object`):

Apify Proxy is on by default.

## Actor input object example

```json
{
  "keywords": [
    "스타벅스"
  ],
  "sortBy": "newest",
  "maxArticlesPerKeyword": 100,
  "includeArticleContent": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Naver News article: keyword, day, headline, press, age, snippet, article link and Naver News link; with 'Open each article' also the exact time, sections and full text.

## `runSummary` (type: `string`):

What the run wrote and how it ended (the RUN_SUMMARY record in the default key-value store).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "스타벅스"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mochiboo/naver-news-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["스타벅스"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("mochiboo/naver-news-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "스타벅스"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call mochiboo/naver-news-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mochiboo/naver-news-search-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/M4SwHAj3tRcvOZDqi/builds/uRNkpguSY6BcPcZrA/openapi.json
