# Hacker News Scraper & Change Monitor (`luminar/hackernews-scraper-monitor`) Actor

Search Hacker News, export ranked stories and comments, inspect public author submissions, and track new or updated observations with clear coverage.

- **URL**: https://apify.com/luminar/hackernews-scraper-monitor.md
- **Developed by:** [Luka](https://apify.com/luminar) (community)
- **Categories:** Developer tools, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.08 / 1,000 verified item or profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Turn Hacker News topics and discussions into a repeatable research feed. Find stories and comments, export their public context, and see what is new or updated when you run the same watch again.

- Search a topic or collect Top, Newest, Best, Ask HN, Show HN and Jobs.
- Keep source IDs, discussion links, points, dates and optional comments together.
- Follow repeat observations with stable item and change IDs.

![Actual Hacker News search results](https://api.apify.com/v2/key-value-stores/nKdFJ0TdZl4DIhHIf/records/sample-output.png)

### 🚀 Start in 60 seconds

1. Keep **Get current data → Keyword search**.
2. Enter a topic, such as `kubernetes`, and choose a result limit.
3. Run the Actor and export the Results as JSON, CSV or Excel. Read the coverage row alongside the items.

The default returns up to 200 newest matching stories. On the Free or Starter tier, 200 results cost **$0.037** including the collection charge. To try one result, set Maximum results to 1: **$0.002175**. Comments are off by default.

### 🎯 Choose the right workflow

| Source | Use it for | Required input |
|---|---|---|
| Keyword search | Topics, products, stories and comments | Search words, or an empty search |
| Ranked feed | The current Top, Newest, Best, Ask, Show or Jobs list | A feed |
| Known items | A discussion or comment you already know | Item IDs from its `id=` link |
| User submissions | Public submissions by an author | Public username |

Use **Get current data** for exports. Use **Track new and updated items** for sequential repeat checks with the same inputs and watch name. The first monitoring run saves a starting point by default. Subsequent runs compare against that saved watch. Existing matches can optionally be emitted as `NEW`.

`NEW` means first observed by this watch; `UPDATED` means its contents, points or discussion data changed. It does not mean a product is newly launched. Dropping out of a feed or search never creates a removal event.

### 📦 What you get

Results contain `item`, optional `profile`, `change` and `coverage` rows. Filter by `recordType` in your downstream workflow. Each item includes its source ID, title/text when available, public author, points, reported comment count, publication time and canonical Hacker News link. Missing source fields are `null`.

Optional comments stay inside their parent item's `comments` array, with IDs, text, author, depth and parent links. Their count and depth may be limited; `commentsCoverage` makes this visible. Public profiles include biography, karma and a submission count, without private account information.

For JSON processing, use `stableId` to update current records and `changeId` to deduplicate change events. CSV exports can contain nested comments as structured values; JSON keeps the full structure.

### 🎛️ Input guide

**Search and filters:** choose date or relevance order, item types, author, minimum points/comments, a UTC date range and an optional linked website domain. Domain filtering includes subdomains. External pages are not fetched.

**Comments:** default five direct replies per item when enabled. Raise the count up to 100 and depth up to 10. There is also a total limit of 10,000 included comments per run. Truncation remains visible.

**User submissions:** stories are included by default; add Comments to item types to include the author's comments. A requested public profile adds one paid row beyond the item limit.

**Limits:** up to 10,000 paid items and 500 explicitly supplied IDs. Feed size, time, unavailable records and output size can reduce delivery. Set the spending limit high enough for the maximum requested count; a lower limit is rejected before collection.

**Monitoring:** keep the same watch name, source, filters, comment settings and result limit. Changed settings create a separate watch. Run the same watch sequentially. If a run has unfinished delivery, recover that original run before starting another. Watches retain up to 10,001 observed identities; start a new watch when this is reached.

### 💰 Pricing

Each verified collection costs **$0.002**, including a verified empty collection. Each delivered item or public profile adds the rate below. Unverified failed collections and their data are free.

| Apify tier | Per item/profile | 200 results, including collection | 1,000 results, including collection |
|---|---:|---:|---:|
| Free | $0.000175 | $0.037 | $0.177 |
| Starter | $0.000175 | $0.037 | $0.177 |
| Scale | $0.00015 | $0.032 | $0.152 |
| Business | $0.00008 | $0.018 | $0.082 |

Enterprise tiers use the Business rate. The rates follow the active tiered offer; check your tier before running. Requested nested comments, `NEW`/`UPDATED` rows and coverage are included. Current observations are charged again on repeat monitoring even when unchanged. A collection with no matches costs $0.002; a run with 100 items plus one requested profile charges for 101 records. Platform usage pass-through is off.

The fixed collection charge means tiny runs are not always cheaper than a per-result-only alternative. Compare the complete requested workload, including comments and any profile row.

### ✅ Coverage you can trust

`COMPLETE` means the requested current source scope was exhausted; `EMPTY_CONFIRMED` means a verified scope contained no matching items. `CAPPED` means a declared result, comment, size or time boundary limited collection. `PARTIAL` means some requested data could not be verified. `FAILED` means no trustworthy collection was delivered.

Ranked feeds are snapshots of the lists Hacker News publishes, not a complete archive. Keyword search uses the public search index and can lag behind current item pages. Newest searches divide broad time ranges when needed; relevance searches remain capped at 1,000 matches. Narrow the date range for a more focused export. Search estimates can change during collection, and very dense time windows may remain capped.

Deleted/dead flags are reported only when explicitly supplied by the source. Missing items, changing ranks, delayed indexing and incomplete comment trees never prove deletion. A partial watch retains older observations and emits changes only for verified current records.

### 🔌 API and automation

Call `luminar/hackernews-scraper-monitor` from the Apify API, or use the Apify integration in n8n, Make or Zapier. For a topic watch:

```json
{"workflow":"monitor","mode":"search","query":"kubernetes","maxResults":100,"stateNamespace":"my-topic"}
```

Run sequentially with unchanged settings. Store current items by `stableId`; filter `recordType=change` for notifications and deduplicate with `changeId`. This Actor only returns data; it does not create schedules, send messages or change other services.

### ⚠️ Not yet supported

- Complete global historical coverage, or more than the source search window in relevance order.
- Inferred removals, sentiment or virality scores, and private account data.
- External article crawling, GitHub enrichment, posting, voting or messaging.
- Concurrent runs of the same watch, automatic migration of incompatible old watches, or an unlimited saved history.

### ❓ FAQ and support

**Does an empty result mean the source was blocked?** No. Verified empty and unverified failure have different coverage and billing.

**Are all comments always included?** No. The selected count/depth, total comment budget and source availability determine coverage. Check `commentsCoverage`.

**Why did an old story appear as NEW?** It was newly observed by your saved watch. The source publication date is separate.

**What should I send with a support request?** The Apify run ID, your intended result and the relevant coverage row. Keep passwords and private credentials out of support messages.

# Actor input Schema

## `workflow` (type: `string`):

Get current data, or compare repeated runs of the same watch.

## `mode` (type: `string`):

Search topics, read a ranked feed, look up known item IDs, or inspect a public author.

## `query` (type: `string`):

Words or a phrase to find in Hacker News. Used for keyword search. Empty searches are allowed.

## `feed` (type: `string`):

Used for ranked feed mode. The source publishes a limited current list; Best is not an all-time archive.

## `username` (type: `string`):

Required for User submissions. For example pg. Story submissions are included by default.

## `itemIds` (type: `array`):

For Known items. Paste the numbers after id= in Hacker News discussion links. Up to 500 IDs.

## `sort` (type: `string`):

Newest supports time-window pagination beyond the first 1,000 indexed matches. Relevance remains limited to the first 1,000.

## `itemTypes` (type: `array`):

Types for keyword search. Include Comments here to include comments in User submissions too.

## `author` (type: `string`):

Keep items posted by this public username.

## `minPoints` (type: `integer`):

Keep items with at least this many visible points. Zero disables this filter.

## `minComments` (type: `integer`):

Keep stories with at least this many reported comments. Zero disables this filter.

## `domain` (type: `string`):

Optional domain such as github.com. Includes its subdomains. Linked pages are not visited.

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

Optional YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ in UTC.

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

Optional UTC date. A date without a time includes that full day.

## `includeComments` (type: `boolean`):

Include public comments with IDs, authors, text and parent links. These nested comments are included in the item price.

## `maxCommentsPerItem` (type: `integer`):

Maximum nested comments in each item, across all selected depths. Default five. Total nested comments are limited to 10,000 per run.

## `commentDepth` (type: `integer`):

One includes direct replies only. Up to ten levels; count and time limits still apply.

## `includeUserProfile` (type: `boolean`):

User submissions mode can include one extra paid profile row with public karma, biography and submission count.

## `stateNamespace` (type: `string`):

Keep the same name and inputs for sequential repeat runs. Changing them starts a separate watch. Use letters, digits, hyphens or underscores.

## `firstRunBehavior` (type: `string`):

Save the starting observations quietly, or label existing matches as new to this watch.

## `maxResults` (type: `integer`):

Maximum paid items. User profile mode may add one profile. Feed size and source limits still apply.

## `maxBuyerChargeUsd` (type: `number`):

Reject a run before collection if its maximum requested charge exceeds this amount. Failed unverified data is free.

## `maxRuntimeSecs` (type: `integer`):

Maximum time for source collection. Additional time is reserved for safely finishing delivery. A time-limited result has incomplete coverage.

## Actor input object example

```json
{
  "workflow": "collect",
  "mode": "search",
  "query": "kubernetes",
  "feed": "top",
  "username": "",
  "itemIds": [],
  "sort": "date",
  "itemTypes": [
    "story"
  ],
  "author": "",
  "minPoints": 0,
  "minComments": 0,
  "domain": "",
  "dateFrom": "",
  "dateTo": "",
  "includeComments": false,
  "maxCommentsPerItem": 5,
  "commentDepth": 1,
  "includeUserProfile": true,
  "stateNamespace": "default",
  "firstRunBehavior": "seed_only",
  "maxResults": 200,
  "maxBuyerChargeUsd": 1,
  "maxRuntimeSecs": 180
}
```

# Actor output Schema

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

Current items, profiles, changes and coverage.

## `summary` (type: `string`):

Counts, coverage and the calculated buyer charge.

# 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 = {
    "workflow": "collect",
    "mode": "search",
    "query": "kubernetes",
    "feed": "top",
    "username": "",
    "itemIds": [],
    "sort": "date",
    "itemTypes": [
        "story"
    ],
    "author": "",
    "minPoints": 0,
    "minComments": 0,
    "domain": "",
    "dateFrom": "",
    "dateTo": "",
    "includeComments": false,
    "maxCommentsPerItem": 5,
    "commentDepth": 1,
    "includeUserProfile": true,
    "stateNamespace": "default",
    "firstRunBehavior": "seed_only",
    "maxResults": 200,
    "maxBuyerChargeUsd": 1,
    "maxRuntimeSecs": 180
};

// Run the Actor and wait for it to finish
const run = await client.actor("luminar/hackernews-scraper-monitor").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 = {
    "workflow": "collect",
    "mode": "search",
    "query": "kubernetes",
    "feed": "top",
    "username": "",
    "itemIds": [],
    "sort": "date",
    "itemTypes": ["story"],
    "author": "",
    "minPoints": 0,
    "minComments": 0,
    "domain": "",
    "dateFrom": "",
    "dateTo": "",
    "includeComments": False,
    "maxCommentsPerItem": 5,
    "commentDepth": 1,
    "includeUserProfile": True,
    "stateNamespace": "default",
    "firstRunBehavior": "seed_only",
    "maxResults": 200,
    "maxBuyerChargeUsd": 1,
    "maxRuntimeSecs": 180,
}

# Run the Actor and wait for it to finish
run = client.actor("luminar/hackernews-scraper-monitor").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 '{
  "workflow": "collect",
  "mode": "search",
  "query": "kubernetes",
  "feed": "top",
  "username": "",
  "itemIds": [],
  "sort": "date",
  "itemTypes": [
    "story"
  ],
  "author": "",
  "minPoints": 0,
  "minComments": 0,
  "domain": "",
  "dateFrom": "",
  "dateTo": "",
  "includeComments": false,
  "maxCommentsPerItem": 5,
  "commentDepth": 1,
  "includeUserProfile": true,
  "stateNamespace": "default",
  "firstRunBehavior": "seed_only",
  "maxResults": 200,
  "maxBuyerChargeUsd": 1,
  "maxRuntimeSecs": 180
}' |
apify call luminar/hackernews-scraper-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,luminar/hackernews-scraper-monitor"
        }
    }
}
```

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/cBoYHmZeMhjKGNqz6/builds/uVPAfBRQYjv7dHPiA/openapi.json
