# Hacker News Search API: Stories and Comments (`itayozer9/hacker-news-search`) Actor

Search Hacker News stories and comments by keyword, author, date range, points and type through the official HN Search API. Small clean JSON for AI agents, optional comment threads, only-new mode for alerts. Pay per result.

- **URL**: https://apify.com/itayozer9/hacker-news-search.md
- **Developed by:** [Itay Ozer](https://apify.com/itayozer9) (community)
- **Categories:** News, AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.15 / 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

## Hacker News Search API: Stories and Comments

Search Hacker News stories and comments by keyword, author, date range, points and type, and get back small, clean JSON. Built for AI agents, research scripts and keyword alerts: one call, no HTML to parse, no API key.

Data comes from the official Hacker News search API (hn.algolia.com, the search linked at the bottom of every Hacker News page). That means no scraping of news.ycombinator.com, no blocked pages, no captchas and no proxy costs, which is why the price per result is this low.

### What you can do with it

- **Find discussions about a topic**: every HN story about "vector database" with 50+ points this year.
- **Monitor mentions**: schedule it with **Only new since last run** and get just the stories or comments that appeared since the last check (brand, product, competitor or job alerts).
- **Read the room**: turn on **Include comment threads** and each story comes with its comments as plain text, in thread order, ready for an LLM to summarize.
- **Track launches**: newest Show HN or Launch HN posts, or what is on the front page right now.
- **Follow a person's public posts**: filter by HN username.

### What you get

One dataset item per story or comment:

- `title`, `url` (the linked article), `hnUrl` (the HN discussion)
- `points`, `numComments`, `createdAt` (ISO 8601, UTC)
- `type` (`story`, `comment`, `poll`, `job`) and `labels` (`show_hn`, `ask_hn`, `launch_hn`, `front_page`)
- `author`: the poster's public HN username
- `text`: Ask HN or Show HN text, or the comment, as plain text (HTML and entities removed, links kept as URLs)
- For comments: `storyId`, `storyTitle`, `storyUrl`, `parentId`
- `comments` (only with comment threads on): `id`, `parentId`, `depth`, `author`, `text`, `createdAt` for each comment

Fields the source does not have are `null`, never guessed.

### Input

| Field | Example | Notes |
|---|---|---|
| `query` | `sqlite` | Keywords. Quotes for an exact phrase: `"vector database"`. Empty = everything matching the other filters |
| `type` | `story` | `story`, `comment`, `show_hn`, `ask_hn`, `launch_hn`, `job`, `poll`, `front_page`, or `all` |
| `author` | `pg` | HN username, case-sensitive |
| `dateFrom` | `2026-10-01` or `7 days` | From this date or time (UTC). Relative: `24 hours`, `7 days`, `2 weeks` |
| `dateTo` | `2026-10-31` | Up to this date (a plain date includes the whole day) |
| `minPoints` | `100` | At least this many points |
| `minComments` | `20` | At least this many comments |
| `sortBy` | `relevance` | `relevance` (best match, up to 1,000) or `date` (newest first, up to 5,000) |
| `maxItems` | `50` | 1 to 5,000, default 50. You pay only for results returned |
| `includeComments` | `true` | Add each story's comment thread |
| `maxCommentsPerStory` | `100` | 1 to 500, default 100 |
| `onlyNew` | `true` | Return only results this search has not returned before |

```json
{
    "query": "postgres",
    "type": "story",
    "minPoints": 200,
    "dateFrom": "2026-01-01",
    "maxItems": 20,
    "includeComments": true,
    "maxCommentsPerStory": 50
}
```

### Output example

```json
{
    "id": "27016630",
    "type": "story",
    "labels": [],
    "title": "Hosting SQLite databases on GitHub Pages or any static file hoster",
    "url": "https://phiresky.github.io/blog/2021/hosting-sqlite-databases-on-github-pages/",
    "hnUrl": "https://news.ycombinator.com/item?id=27016630",
    "author": "phiresky",
    "points": 1812,
    "numComments": 244,
    "createdAt": "2021-05-02T16:43:15.000Z",
    "text": null,
    "storyId": null,
    "storyTitle": null,
    "storyUrl": null,
    "parentId": null,
    "comments": [
        {
            "id": "27016787",
            "parentId": "27016630",
            "depth": 1,
            "author": "Gehinnn",
            "text": "TL;DR:\nCompile SQLite to JS with emscripten, implement a virtual fs in JS to stream chunks of a statically hosted (readonly) SQL database. ...",
            "createdAt": "2021-05-02T17:00:45.000Z"
        }
    ],
    "query": "sqlite",
    "scrapedAt": "2026-10-31T18:48:21.631Z"
}
```

### Pricing

Pay per result. Comment threads are included at no extra charge.

| Event | Price | When |
|---|---|---|
| Actor start | $0.00005 | Once per run (Apify's standard start event) |
| Result | $0.00015 | Every story or comment in your dataset |

Example: 1,000 results cost $0.15 plus $0.00005 for the start.

Searches that find nothing are not charged per result, and neither is a story whose comment thread could not be read (it is saved without comments, free). The actor reads your run's maximum charge before it searches and returns only as many results as that covers, so a run never goes over the limit you set.

### Only-new mode for alerts

With `onlyNew` on, the actor remembers which results each search already returned (per search and per saved task, in a key-value store in your own Apify account) and returns only new ones. Schedule a task every hour and you get a feed of new mentions. Set `maxItems` above the number of new results you expect between two runs. A run with nothing new returns no items and the status message says so.

### Limits

- Relevance search returns at most 1,000 results per run (the search API's limit). Sort by date to get up to 5,000.
- Data is as fresh as the HN search index, usually within minutes of posting (a cloud test on 2026-10-31 started 38 seconds after the newest comment it returned was posted). Points and comment counts are current at search time.
- Comment threads add about half a second per story, so 100 stories with threads take under a minute.
- Deleted and dead comments are left out of threads (their live replies stay).

### FAQ

**Where does the data come from?**
From the public Hacker News Search API run by Algolia at hn.algolia.com/api, which Hacker News links to as its search. The actor stays far below its published limit of 10,000 requests per hour.

**Why did I get fewer results than `maxItems`?**
The search had fewer matches, your filters narrowed it, only-new mode skipped results you already have, or your run's maximum charge covered fewer results.

**Can I call it from an AI agent or MCP client?**
Yes. Inputs are plain fields, the output is small JSON with plain-text bodies, and it runs with limited permissions, so it needs no access to your other Apify data. It also works from schedules and the API.

**Is there personal data in the results?**
Results are public Hacker News posts. The `author` field is the poster's public HN username, as shown on the site. The actor adds nothing else about people: no profiles, emails or karma.

**Something broke or a field is missing. What do I do?**
Open an issue on the Issues tab with your run link. Issues are answered within a few days.

# Actor input Schema

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

Words to find in titles, URLs, story text and comments. Use quotes for an exact phrase, for example "vector database". Leave empty to list everything that matches the other filters (for example the newest Show HN posts).

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

What to search. all = stories, comments, polls and jobs together.

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

Only posts by this Hacker News username (case-sensitive, for example pg).

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

Only posts created at or after this time: 2026-10-01, 2026-10-01T12:00:00Z, or relative such as "24 hours", "7 days", "2 weeks". Dates are UTC.

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

Only posts created at or before this time. A plain date includes the whole day (UTC).

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

Only posts with at least this many points (upvotes). 0 = no limit.

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

Only stories with at least this many comments. 0 = no limit.

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

relevance = best matches first (up to 1,000 results). date = newest first (up to 5,000 results).

## `maxItems` (type: `integer`):

Most results to return (1 to 5,000). You pay only for results returned.

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

Add each story's comments (plain text, thread order, with depth and parent id) to its result. No extra charge, but runs take longer.

## `maxCommentsPerStory` (type: `integer`):

Cap on comments added to each story when comment threads are on (1 to 500).

## `onlyNew` (type: `boolean`):

For schedules and alerts: return only results this same search has not returned before (remembered per search and per saved task). Sorts by date.

## Actor input object example

```json
{
  "query": "sqlite",
  "type": "story",
  "minPoints": 0,
  "minComments": 0,
  "sortBy": "relevance",
  "maxItems": 20,
  "includeComments": false,
  "maxCommentsPerStory": 100,
  "onlyNew": false
}
```

# Actor output Schema

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

One item per story or comment.

# 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 = {
    "query": "sqlite",
    "type": "story",
    "sortBy": "relevance",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("itayozer9/hacker-news-search").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 = {
    "query": "sqlite",
    "type": "story",
    "sortBy": "relevance",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("itayozer9/hacker-news-search").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 '{
  "query": "sqlite",
  "type": "story",
  "sortBy": "relevance",
  "maxItems": 20
}' |
apify call itayozer9/hacker-news-search --silent --output-dataset

```

## MCP server setup

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

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/0CjUyfx4YCjbpDtdp/builds/JoBZfskxPdPUIiJvn/openapi.json
