# Hacker News Mentions Scraper - Stories, Comments & Evidence

Find literal brand, product or topic mentions in public Hacker News stories and comments. Export matching excerpts, thread links and saved changes using the public Algolia index. No API key.

Canonical product page: https://mayd-it.com/data-tools/actors/hacker-news-mentions-scraper/
Public Actor: https://apify.com/maydit/hacker-news-mentions-scraper

## Example input

```json
{
  "queries": [
    "OpenAI"
  ],
  "itemType": "comment",
  "maxResults": 10,
  "maxCandidatesPerQuery": 100
}
```

## Full guide

![Mentions you can trace to the text — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/hacker-news-mentions-scraper-3f28ab92b419.png?signature=Dwr51zJI83sg8vLZPd3y)

## Mentions you can trace to the text

Build a repeatable brand, product or topic research watchlist from the public Hacker News Algolia index. Each saved story or comment includes literal match evidence and a discussion link.

[Open this Actor in Console](https://console.apify.com/actors/CcWenJwr0DRG9oUe6/input) · [First run](#try-this-actor) · [Results](#result-preview) · [Cost](#usage-and-pricing) · [Full guide](#full-guide)

## Try this Actor

1. **Choose a small scope.** Use the existing **OpenAI Mentions in Hacker News Comments** example below: ten saved comments at most, drawn from a candidate window of one hundred.
2. **Run and review.** Open the dataset and inspect `matchedTerms` to see which source text qualified. The run's key-value-store `SUMMARY` separates inspected candidates, saved matches and source failures.
3. **Use the results.** Export JSON for matching excerpts and saved comparisons, or CSV for a discussion list. Follow the item or thread link when reviewing context.

**Read this before using the data:** Literal matches do not establish sentiment, purchase intent or the truth of a post. The search index can lag Hacker News, and its bounded result window is not exhaustive history. Missing later results do not prove deletion.

**OpenAI Mentions in Hacker News Comments** — copy this input into the JSON editor in Console.

```json
{
  "queries": [
    "OpenAI"
  ],
  "itemType": "comment",
  "maxResults": 10,
  "maxCandidatesPerQuery": 100
}
```

## Result preview

The dataset view highlights these columns:

- **Mention ID** · `mentionId`
- **Story or comment** · `itemType`
- **Item or thread title** · `title`
- **Text** · `text`
- **Public author handle** · `author`
- **Indexed publication time** · `publishedAt`

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

## Usage and pricing

Base result rate on the FREE tier: **$1 per 1,000 mention observations**. The [Pricing tab](https://apify.com/maydit/hacker-news-mentions-scraper/pricing) shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.

---

## Full guide

Find literal brand, product and topic mentions in public Hacker News stories and comments. Get matching excerpts, canonical discussion links and saved comparisons for a repeatable research watchlist.

The Actor uses the documented public [Hacker News Search API by Algolia](https://hn.algolia.com/api). No API key, account, proxy or browser is required. It does not crawl linked articles or infer sentiment, purchase intent or personal profiles.

### Quick start

Run with `{}` to save up to 20 recent indexed story/comment mentions of `OpenAI`. The Console prefill uses the same phrase.

```json
{
  "queries": ["OpenAI"],
  "itemType": "comment",
  "maxResults": 20,
  "maxCandidatesPerQuery": 100
}
```

Pricing is **$0.001 per saved mention ($1 per 1,000)**. A mention is one unique story or comment ID. Duplicate matches across phrases, rejected fuzzy matches, filtered records, unchanged observations skipped by `onlyChanges`, and error diagnostics are not saved as paid rows. Spending limits may stop a run before the requested window is finished.

### Literal evidence, not inferred relevance

Every saved item must match the current phrase in actual source text:

- A story may match its title, self-text or linked URL.
- A comment must match its own text. A parent story title alone does not qualify it.

Matching is a case-insensitive **literal substring**, so `AI` also matches those adjacent characters inside longer words. Use a more specific phrase when that is too broad. Algolia typo/prefix matching is disabled where supported, and an independent local check rejects fuzzy results. Each row's `matchedTerms` contains matching fields and short excerpts for all configured phrases found in that item.

The service is an index, not a live verification of the underlying item. Edits, deletion and metrics may lag [Hacker News's official item API](https://github.com/HackerNews/API). A missing item in a later search does not prove deletion.

### Inputs

| Input | Behavior |
| --- | --- |
| `queries` | Up to 10 literal phrases, at most 100 characters each. Omitted or empty uses `OpenAI`. Phrases are normalized to lowercase, deduplicated and processed in sorted order. |
| `itemType` | `all` (default), `story` or `comment`. |
| `sort` | `recent` (default) uses publication order from the index; `relevance` uses Algolia ranking. Multiple query results are not globally resorted. |
| `storyTag` | `any` (default), `ask_hn` or `show_hn`. A restricted tag requires `itemType: "story"`. |
| `author` | Optional exact public Hacker News handle. No profile or contact enrichment. |
| `startDate`, `endDate` | Optional real `YYYY-MM-DD` dates, inclusive in UTC, filtering the item publication date. |
| `maxCandidatesPerQuery` | Default 100, range 1-1,000. Candidate window before local filtering and deduplication. This is not a promise of that many saved matches. |
| `pageSize` | Default 100, range 1-100 indexed candidates per request. Smaller pages require more requests. |
| `maxResults` | Default 20, maximum 1,000 unique saved rows across all queries. |
| `comparePrevious` | Return matching rows with new, changed or unchanged comparison status. Default false. |
| `onlyChanges` | Implies comparison and skips unchanged observations. Default false. |
| `snapshotName` | History namespace, default `default`; 1-80 letters, digits, underscores or hyphens. |
| `maxRunSeconds` | Default 240; range 30-3,600. Also respects the platform deadline minus 25 seconds. |

### Output

| Fields | Meaning |
| --- | --- |
| `mentionId`, `itemId`, `itemType` | Stable Hacker News item identity and `story`/`comment` type. |
| `title`, `storyTitle` | A story's title or a comment's thread title. If comment thread title metadata is absent, `title` is the explicit label `Comment <itemId>`. Literal comment evidence still comes from its own text. |
| `text`, `textHash`, `textTruncated` | Normalized self-text/comment text with HTML entities decoded. Output is capped at 50,000 characters; SHA-256 and evidence are computed from the full received text. Ordinary link stories can have empty self-text. |
| `author`, `publishedAt` | Public author handle when present and the item's indexed publication time in UTC. |
| `points`, `commentCount` | Public indexed counts when supplied. Comment scores/counts are usually absent and remain null rather than zero. |
| `storyId`, `parentId` | Thread and immediate parent IDs when published by the index. Stories point to their own thread and have no parent. Missing comment ancestry remains null. |
| `itemUrl`, `threadUrl` | Canonical Hacker News item and thread links. |
| `sourceUrl` | Linked article/page URL metadata only; content is not downloaded. A comment may use its thread's linked URL. Missing or unsafe URL metadata is null. |
| `matchedTerms` | Literal phrase, source field and matching excerpt. |
| `source`, `indexUpdatedAt`, `observedAt` | Index provenance and timestamps. Missing index update time remains null. |
| `comparisonStatus`, `changedFields`, `previous`, `previousObservedAt` | Comparison against prior saved observations. |

### Bounded search coverage

Algolia exposes at most about **1,000 hits per search**, even when `nbHits` is much larger. Each query's `SUMMARY.sourceCoverage` separates reported hits/pages from inspected candidates, fetched pages and saved results. Requested candidate/result caps are successful bounded checks, not full-history claims. Narrow dates or phrases for deeper targeted research.

Deleted/dead indexed items are excluded when flagged. Unexpectedly empty pages, repeated pages, invalid envelopes and unusable records are reported explicitly. A candidate window with no literal match can legitimately save zero rows.

### Repeat runs and saved history

Enable `comparePrevious` to return `new`, `changed` or `unchanged`; otherwise status is `not_requested`. `onlyChanges` saves new/changed observations only. Changes include title, full text hash, linked URL, ancestry, author, points and comment count. Thus discussion metric updates can be meaningful changes even when text is unchanged. Index update and observation timestamps do not trigger changes.

The first comparison run warns that matching observations establish history. A row marked `new` reports the comparison result; **`SUMMARY.historyUpdated` confirms whether history was committed**. An unchanged rerun can succeed with zero saved rows.

The named store `maydit-hacker-news-mention-history` is scoped by `snapshotName`, sorted queries, type, story tag, author and date filters. Only confirmed saved rows advance per-item history. Limits, filters, failures and missing search results do not remove prior observations. History is capped at 20,000 identities per scope.

Use **one concurrent writer per history scope**. A final reread detects some concurrent changes, but this is not a transactional lock. Malformed/incompatible history fails clearly; a new `snapshotName` starts fresh.

### Failure and limit handling

`SUMMARY` in the default key-value store records partial source failures, unusable hits, filters, duplicates, unchanged rows, candidate windows and time/spending stops. When all sources fail and no usable observations are saved, the run fails after writing its summary. Saved rows survive a later-page outage, with status `partial`. Errors are never written as mention rows.

All requests use the public API, a 25-second request deadline, the overall run budget and bounded retries. No login, rate-limit or challenge bypass is attempted. This workflow provides public evidence for research; it does not establish a person's intent or the truth of user-generated claims.

### Ready-to-run examples

The following exact inputs also appear in `examples.json`.

#### OpenAI Mentions in Hacker News Comments

Find 10 recent indexed comments with a literal OpenAI mention in the comment itself, with evidence and canonical thread links.

Use the [copyable first-run input](#try-this-actor) above.

#### PostgreSQL Stories on Hacker News

Read 10 recent indexed stories whose title, self-text or linked URL literally mentions PostgreSQL. Includes public scores and discussion links.

```json
{
  "queries": [
    "PostgreSQL"
  ],
  "itemType": "story",
  "maxResults": 10,
  "maxCandidatesPerQuery": 100
}
```

#### Show HN AI Stories - Saved Observation Watch

Compare 10 indexed Show HN stories with literal AI text against prior saved observations. AI is a substring phrase, not an inferred category.

```json
{
  "queries": [
    "AI"
  ],
  "itemType": "story",
  "storyTag": "show_hn",
  "maxResults": 10,
  "maxCandidatesPerQuery": 100,
  "comparePrevious": true,
  "snapshotName": "show-hn-ai-demo"
}
```

## Help with your run

Open the **Issues** tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

[Explore more Mayd-It Actors](https://apify.com/maydit)

## Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.
