# Hacker News Keyword Mention Monitor (`enviable_shell/hn-keyword-mention-monitor`) Actor

Monitor Hacker News stories and comments for brand, competitor, product, and technology mentions.

- **URL**: https://apify.com/enviable\_shell/hn-keyword-mention-monitor.md
- **Developed by:** [佳斌 王](https://apify.com/enviable_shell) (community)
- **Categories:** News, Developer tools, Lead generation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Hacker News Keyword Mention Monitor

Monitor Hacker News stories and comments for brand, competitor, product, domain, and technology mentions. Use it to find customer pain points, competitor comparisons, launch chatter, pricing debates, and integration requests from a technical audience.

The Actor uses the public HN Algolia API, so it does not need a login, proxy, browser, or GitHub/Product Hunt token.

### Who should use this

- Founders tracking how HN talks about their product, category, or competitors
- Product marketers looking for authentic technical pain points and comparison language
- DevRel teams monitoring developer tool mentions and integration requests
- VC, accelerator, and research teams watching AI/devtool/startup trends
- Indie hackers who want a lightweight competitor and audience-monitoring feed

### What it does

- Searches HN stories and comments for multiple keywords in one run
- Returns structured mention records with HN URL, external URL, author, points, comments, snippet, intent, and signals
- Classifies mentions as comparison, pain point, launch, hiring, pricing, integration, or general mention
- Supports strict keyword matching for clean monitoring and broad Algolia matching for maximum recall
- Optionally sends a JSON notification to Slack, Discord, Zapier, Make, n8n, or your own webhook
- Produces a Markdown summary in the key-value store under `SUMMARY`

### Best first run

Track a few AI developer tools across recent HN stories and comments:

```json
{
  "keywords": ["OpenAI", "Claude", "Cursor", "Codex"],
  "maxItemsPerKeyword": 25,
  "searchIn": "all",
  "matchMode": "strict",
  "webhookUrl": "",
  "includeText": true
}
````

For brand monitoring, keep `matchMode` as `strict`. If you are doing exploratory research and want wider recall, use `broad`.

### Scheduled monitoring examples

Run the Actor on an Apify schedule to turn it into a lightweight alerting workflow.

#### Daily brand and competitor monitor

```json
{
  "keywords": ["yourproduct.com", "Your Product", "Competitor A", "Competitor B"],
  "maxItemsPerKeyword": 25,
  "searchIn": "all",
  "matchMode": "strict",
  "webhookUrl": "https://hooks.zapier.com/hooks/catch/...",
  "failOnWebhookError": false,
  "includeText": false
}
```

Suggested schedule: every morning.

#### Weekly AI devtools digest

```json
{
  "keywords": ["Claude Code", "Codex", "Cursor", "Windsurf", "OpenCode"],
  "maxItemsPerKeyword": 100,
  "searchIn": "all",
  "matchMode": "strict",
  "minPoints": 0,
  "includeText": true
}
```

Suggested schedule: weekly, then export the dataset to CSV or send the summary to a webhook.

#### Product pain-point research

```json
{
  "keywords": ["authentication", "billing", "observability", "vector database"],
  "maxItemsPerKeyword": 100,
  "searchIn": "comments",
  "matchMode": "broad",
  "includeText": true
}
```

Suggested use: read rows where `intent` is `pain-point`, `pricing`, `comparison`, or `integration`.

### Optional webhook alerts

Set `webhookUrl` to send the run summary and top mentions to an automation tool. The payload is generic JSON and includes a Slack-compatible `text` field.

Works with:

- Slack incoming webhooks
- Discord webhooks
- Zapier Catch Hook
- Make custom webhook
- n8n webhook trigger
- Any HTTP endpoint that accepts JSON

The Actor stores webhook status in `WEBHOOK_RESULT`. By default, webhook failures do not fail the run. Set `failOnWebhookError` to `true` if you want strict alert delivery.

### Sample output

```json
{
  "keyword": "Claude",
  "matchType": "comment",
  "title": "Ask HN: What is your (AI) dev tech stack / workflow?",
  "hnUrl": "https://news.ycombinator.com/item?id=48415368",
  "storyUrl": "https://news.ycombinator.com/item?id=48413629",
  "author": "example_user",
  "createdAt": "2026-06-05T17:06:34Z",
  "snippet": "I use Claude Code, Codex, and terminal-first workflows...",
  "exactMatch": true,
  "intent": "integration",
  "signals": {
    "competitorComparison": false,
    "pricing": false,
    "painPoint": false,
    "launch": false,
    "hiring": false,
    "integration": true,
    "ai": true
  },
  "relevanceScore": 11
}
```

### Example input

```json
{
  "keywords": ["OpenAI", "Claude", "Cursor", "Codex"],
  "maxItemsPerKeyword": 50,
  "searchIn": "all",
  "matchMode": "strict",
  "createdAfter": "2026-01-01",
  "minPoints": 0,
  "webhookUrl": "https://hooks.zapier.com/hooks/catch/...",
  "failOnWebhookError": false,
  "includeText": true
}
```

### Output fields

- `keyword` - keyword that matched
- `matchType` - `story` or `comment`
- `title` - story title or parent story title
- `hnUrl` - direct HN item URL
- `storyUrl` - parent story URL when the match is a comment
- `url` and `domain` - external story URL when available
- `author`, `points`, `commentCount`, `createdAt`
- `snippet` - short context around the keyword
- `exactMatch` - whether the keyword appears directly in title, text, or URL
- `intent` - simple intent classification
- `signals` - booleans for competitor comparison, pricing, pain point, launch, hiring, integration, and AI
- `relevanceScore` - heuristic score combining title/text matches and HN traction

### Use cases

- Brand monitoring for tools, products, or domains
- Competitor monitoring across HN discussions
- Finding unhappy users and integration requests
- Tracking launch mentions and pricing debates
- Building Slack, email, or spreadsheet alerts from Apify datasets

### Why this Actor instead of a generic HN scraper

Generic HN scrapers collect stories and comments. This Actor is tuned for monitoring:

- Multi-keyword input in one run
- Strict keyword filtering to reduce noisy search matches
- Intent labels for pain points, pricing, comparisons, launches, and integrations
- Relevance scoring so you can sort the most important mentions first
- Optional webhook alerts for scheduled monitoring workflows
- Markdown summary saved alongside the dataset

If you only need raw HN stories, use a general HN scraper. If you want recurring product, competitor, or market-intelligence monitoring, use this Actor.

### Practical workflow

1. Start with 3-10 keywords.
2. Keep `matchMode` as `strict` for clean brand or competitor monitoring.
3. Add an Apify schedule.
4. Add `webhookUrl` if you want alerts in Slack, Discord, Zapier, Make, or n8n.
5. Review `SUMMARY` first, then inspect the dataset rows with the highest `relevanceScore`.

# Actor input Schema

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

Brands, competitors, products, domains, or technology terms to monitor.

## `maxItemsPerKeyword` (type: `integer`):

Maximum matching stories/comments to return for each keyword.

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

Search stories, comments, or both.

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

Strict keeps only records where the keyword appears in the title, text, or URL. Broad keeps all Algolia search results for maximum recall.

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

Optional ISO date, for example 2026-01-01. Only mentions created after this date are returned.

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

Only include stories with at least this many points. Comments without story points are kept unless this is used with stories-only filtering.

## `includeText` (type: `boolean`):

Include cleaned story/comment text in output. Snippets are always included.

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

Optional Slack, Discord, Zapier, Make, n8n, or custom webhook URL. The Actor POSTs a JSON payload with the run summary and top mentions.

## `failOnWebhookError` (type: `boolean`):

If enabled, the run fails when the webhook returns an error or cannot be reached. Keep disabled for scheduled monitoring.

## Actor input object example

```json
{
  "keywords": [
    "OpenAI",
    "Claude",
    "Cursor",
    "Codex"
  ],
  "maxItemsPerKeyword": 50,
  "searchIn": "all",
  "matchMode": "strict",
  "minPoints": 0,
  "includeText": true,
  "failOnWebhookError": false
}
```

# Actor output Schema

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

One dataset row per keyword mention, including keyword, story/comment type, HN URL, author, snippet, intent, signals, and relevance score.

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

Markdown summary with mention counts by keyword, mention counts by intent, and top relevant mentions.

# 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 = {
    "createdAfter": "",
    "webhookUrl": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("enviable_shell/hn-keyword-mention-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 = {
    "createdAfter": "",
    "webhookUrl": "",
}

# Run the Actor and wait for it to finish
run = client.actor("enviable_shell/hn-keyword-mention-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "createdAfter": "",
  "webhookUrl": ""
}' |
apify call enviable_shell/hn-keyword-mention-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=enviable_shell/hn-keyword-mention-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hacker News Keyword Mention Monitor",
        "description": "Monitor Hacker News stories and comments for brand, competitor, product, and technology mentions.",
        "version": "0.1",
        "x-build-id": "ATZVyAr5OwQDrOFOS"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/enviable_shell~hn-keyword-mention-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-enviable_shell-hn-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/enviable_shell~hn-keyword-mention-monitor/runs": {
            "post": {
                "operationId": "runs-sync-enviable_shell-hn-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/enviable_shell~hn-keyword-mention-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-enviable_shell-hn-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "keywords"
                ],
                "properties": {
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Brands, competitors, products, domains, or technology terms to monitor.",
                        "default": [
                            "OpenAI",
                            "Claude",
                            "Cursor",
                            "Codex"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItemsPerKeyword": {
                        "title": "Maximum items per keyword",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum matching stories/comments to return for each keyword.",
                        "default": 50
                    },
                    "searchIn": {
                        "title": "Search in",
                        "enum": [
                            "all",
                            "stories",
                            "comments"
                        ],
                        "type": "string",
                        "description": "Search stories, comments, or both.",
                        "default": "all"
                    },
                    "matchMode": {
                        "title": "Match mode",
                        "enum": [
                            "strict",
                            "broad"
                        ],
                        "type": "string",
                        "description": "Strict keeps only records where the keyword appears in the title, text, or URL. Broad keeps all Algolia search results for maximum recall.",
                        "default": "strict"
                    },
                    "createdAfter": {
                        "title": "Created after",
                        "type": "string",
                        "description": "Optional ISO date, for example 2026-01-01. Only mentions created after this date are returned."
                    },
                    "minPoints": {
                        "title": "Minimum story points",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only include stories with at least this many points. Comments without story points are kept unless this is used with stories-only filtering.",
                        "default": 0
                    },
                    "includeText": {
                        "title": "Include full text",
                        "type": "boolean",
                        "description": "Include cleaned story/comment text in output. Snippets are always included.",
                        "default": true
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "Optional Slack, Discord, Zapier, Make, n8n, or custom webhook URL. The Actor POSTs a JSON payload with the run summary and top mentions."
                    },
                    "failOnWebhookError": {
                        "title": "Fail on webhook error",
                        "type": "boolean",
                        "description": "If enabled, the run fails when the webhook returns an error or cannot be reached. Keep disabled for scheduled monitoring.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
