# Hacker News Who is Hiring: structured job posts (`catblik/hn-who-is-hiring`) Actor

Monthly 'Ask HN: Who is hiring?' threads turned into structured, filterable job posts via the official HN Algolia API.

- **URL**: https://apify.com/catblik/hn-who-is-hiring.md
- **Developed by:** [asaf meizner](https://apify.com/catblik) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 job post returneds

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 Who Is Hiring: Structured Job Posts API

Extract job posts from the latest monthly **Ask HN: Who is hiring?** threads into a dataset you can export as JSON, CSV or Excel. Filter by keywords and remote mentions to build a focused hiring feed or research company hiring activity.

The actor reads the official public HN Algolia API. No login, proxies or browser are required. It reads top-level comments with a pipe-separated company header; it does not crawl employer websites.

### Quick start

Return up to 25 posts mentioning Python or Rust from the latest three monthly threads:

```json
{
  "months": 3,
  "keywords": ["python", "rust"],
  "remoteOnly": true,
  "includeDescription": true,
  "maxJobs": 25
}
```

Keywords use case-insensitive substring matching across the post text. A post needs to match only one keyword. An empty keyword list returns all otherwise eligible posts.

### Input

| Field | Default | Meaning |
|---|---|---|
| `months` | `1` | Number of latest monthly hiring threads to read, from 1 to 12. |
| `keywords` | `[]` | Keep posts containing any supplied keyword. |
| `remoteOnly` | `false` | Keep posts whose first line mentions remote. |
| `includeDescription` | `true` | Include the post text with email addresses removed. |
| `maxJobs` | `0` | Maximum posts returned across all threads; 0 means unlimited. |

Start with a small `maxJobs` value to check whether the results fit your use case. The actor does not offer date-range search or persistent deduplication between scheduled runs.

### Output

Each result contains `company`, `headline`, `headerFields`, `remote`, `hybrid`, `visaMentioned`, `internship`, `urls`, `postedAt`, `month`, `hnItemId` and `hnUrl`. It also contains `description` when requested.

Illustrative fields, not a real vacancy:

```json
{
  "company": "Example Company",
  "headline": "Example Company | Python Engineer | REMOTE",
  "headerFields": ["Python Engineer", "REMOTE"],
  "remote": true,
  "hybrid": false,
  "visaMentioned": false,
  "internship": false,
  "urls": ["https://example.com/jobs"]
}
```

`remote` is true when the header mentions remote, false when it mentions onsite without remote, and null otherwise. These are text indicators: a phrase such as “no remote” can still match. `visaMentioned` signals that the word appears, not that sponsorship is offered. Confirm details in the original post using `hnUrl`.

### Scheduled hiring feeds

Schedule the actor in Apify to collect recent posts regularly. Use `hnItemId` to deduplicate results in your own workflow. Each run may return posts you received earlier, and returned posts are charged again. Scheduling does not by itself detect new or changed posts.

### Pricing

The `job-post` event costs **$0.003 per returned post**, or $3 per 1,000 posts. For example, 25 returned posts trigger $0.075 in job-post events. Filtered or skipped comments do not trigger this event. Check the Store pricing panel for any additional start or dataset-item charges before running.

### Coverage and limitations

- Posts are free text. Comments without a pipe-separated first-line header are skipped, so the dataset is not a complete list of every vacancy in a thread.
- Company and header fields are extracted from the poster's text; they are not independently verified. Vacancies may have closed.
- Email addresses are removed from post text and poster usernames are not collected. The actor does not provide an email contact list.
- URLs come from visible post text; some HTML-only links may be absent. The original HN link remains available.
- Results depend on HN Algolia availability and indexing. Temporary failures are retried; a failed thread fetch can produce partial results.
- Data belongs to the original posters. Review source rights and use the information responsibly.

# Actor input Schema

## `months` (type: `integer`):

How many of the latest monthly 'Ask HN: Who is hiring?' threads to read (1-12).

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

Keep only posts containing at least one keyword (case-insensitive), e.g. `rust`, `machine learning`. Empty = all.

## `remoteOnly` (type: `boolean`):

Keep only posts whose header mentions remote.

## `includeDescription` (type: `boolean`):

Add the full post text (email addresses removed).

## `maxJobs` (type: `integer`):

Cap on posts returned. 0 = unlimited.

## Actor input object example

```json
{
  "months": 1,
  "keywords": [],
  "remoteOnly": false,
  "includeDescription": true,
  "maxJobs": 0
}
```

# Actor output Schema

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

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("catblik/hn-who-is-hiring").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("catblik/hn-who-is-hiring").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 '{}' |
apify call catblik/hn-who-is-hiring --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,catblik/hn-who-is-hiring"
        }
    }
}
```

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/mmc6UJlT3J2RyzBic/builds/V8LQGtQiAsNgh6MeG/openapi.json
