# Remote Job History: Hiring Velocity & Ghost Jobs (`keith-apis/remote-job-history`) Actor

Weekly remote-hiring history for 2,400 tech companies from 401 career pages, tracked hourly since July 2026: new and closed roles, days a role stays open, and suspected ghost jobs with reasons. Market-wide trend too. From $0.003 per company.

- **URL**: https://apify.com/keith-apis/remote-job-history.md
- **Developed by:** [Lai Keith](https://apify.com/keith-apis) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 company histories

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

## Remote Job History: hiring velocity, days-open and ghost jobs by company

**Remote Job History is an Apify Actor that returns the remote-hiring history of tech companies: how many remote roles each company opened and closed every week, how long its roles stay open, and which of its open postings look like ghost or evergreen jobs, each with the reason.** The data comes from 401 company career pages (Greenhouse, Lever, Ashby) and five remote job boards, checked every hour since 17 July 2026. Most job scrapers show what is open today; this shows what happened over time, which you can't scrape after the fact.

### What does Remote Job History do?

Pick a mode:

- **`company`** (default): one result per company you name, with its weekly history, summary and suspected ghost jobs.
- **`market`:** one result with the weekly trend for the whole remote tech market.
- **`search`:** find a company's exact name (up to 50 matches), nearly free.

For each company it returns:

- **`summary`:** `roles_total`, `open_now`, `closed_total`, `avg_days_open`, `median_days_open`, `ghost_open`, `first_seen`, `last_seen` and `tracked_since`.
- **`weekly`:** one row per week with `new_roles` and `closed_roles`.
- **`suspected_ghosts`:** open postings that look like ghost or evergreen jobs, each with a `reasons` string such as *"open 208 days (longer than 75% of roles that closed)"* or *"relisted 3× over 63 days"*, plus the posting URL.
- **`coverage`:** `full` or `new-roles-only`, so you always know how much the numbers can tell you (see below).
- **`definitions`:** what every field means, in every result.

### Coverage, stated plainly

- **Remote and remote-eligible roles only.** "OpenAI has 503 open roles" means 503 open roles that can be done remotely.
- **Full history for 296 companies** tracked through their own applicant-tracking system, including OpenAI, GitLab, Canonical, ElevenLabs, Samsara, Grafana Labs, Twilio, Coinbase, Stripe, Ramp, Pinterest and Instacart. A careers page lists every open role, so when a role disappears it has closed; that gives closures, days-open and ghost signals.
- **New roles only for about 2,100 more companies** seen on remote job boards. Job boards show a rolling window, so a listing disappearing there doesn't prove the role closed, and we don't claim it did.
- **History starts 17 July 2026** and grows every day. 319 of the 401 career pages were added on 14 October 2026; each company's `tracked_since` says when its history begins. Weekly numbers before that date only count roles that were still open then.
- **The market trend uses a fixed panel** of the 74 sources tracked since the first full week (20 July 2026), so adding sources never shows up as market growth. The result's `panel` field gives the panel's size and start.
- The data is rebuilt every night; `data_as_of` says when.

### When should I use it?

- **Recruiters and sales teams:** see which companies are scaling remote hiring and which have quietly stopped.
- **Job seekers and career coaches:** check whether a company is really hiring and skip postings that have been relisted for months.
- **Investors and analysts:** hiring velocity is an early signal of growth or cutbacks.
- **Journalists and researchers:** a weekly, defensible measure of the remote tech job market.

### Input

```json
{
  "mode": "company",
  "companies": ["Stripe", "OpenAI", "Grafana Labs"],
  "weeks": 12,
  "includeGhosts": true
}
```

| Field | What it does | Default |
|---|---|---|
| `mode` | `company`, `market` or `search` | `company` |
| `companies` | Company names, case-insensitive, up to 100 per run. Names we don't have are skipped and not charged | — |
| `query` | Part of a company name, for `search` mode | — |
| `weeks` | How many weeks of history to include (1–104) | 12 |
| `includeGhosts` | Include suspected ghost jobs with their reasons | `true` |

Not sure of the exact name? Run `search` with part of it first (for example `graf` finds "Grafana Labs").

### Output

One dataset item per company (shortened):

```json
{
  "type": "company-history",
  "coverage": "full",
  "company": "Stripe",
  "summary": {
    "roles_total": 254, "open_now": 121, "closed_total": 138,
    "avg_days_open": 87.7, "median_days_open": 64.2, "ghost_open": 41,
    "first_seen": "2024-06-14T22:04:50+00:00", "tracked_since": "2026-07-17T13:52:28+00:00"
  },
  "weekly": [{ "week": "2026-10-12", "new_roles": 7, "closed_roles": 7 }],
  "suspected_ghosts": [{ "title": "…", "url": "…", "reasons": "open 208 days (longer than 75% of roles that closed)", "first_seen": "2026-03-31T22:06:45+00:00" }],
  "data_as_of": "2026-10-26T16:34:28+00:00",
  "definitions": { "closed_roles": "distinct roles that disappeared from the company's own ATS that week …" }
}
```

Export the dataset as JSON, CSV or Excel, or pass it to the next Actor.

### How much does it cost?

You pay per result, and only for companies we have:

| Event | Price |
|---|---|
| Company with full history (`coverage: full`) | $0.03 |
| Company with new roles only (`coverage: new-roles-only`) | $0.003 |
| Market trend | $0.02 |
| Company search | $0.001 |

Names we don't recognise are skipped and cost nothing. Apify's free plan includes $5 of monthly credit, enough for about 160 full company histories.

### FAQ

**How do you know a role closed?**
Only from the company's own careers page (Greenhouse, Lever or Ashby), which lists every open role. When a role is no longer listed, it closed that week. Disappearances from job boards are never counted as closures.

**What is a ghost job here?**
A posting that is open much longer than the company's roles usually stay open, or one that has been taken down and relisted several times. It's a signal with a stated reason, not a certainty; some evergreen postings are real.

**Why are the numbers lower than the company's total job count?**
Only remote and remote-eligible roles are tracked. Office-only roles are not included.

**Can I get history from before July 2026?**
No. The history is what was observed from 17 July 2026 on. Older weeks only contain roles that were still open when tracking began, and `tracked_since` marks where real tracking starts for each company.

**Is any personal data included?**
No. Results contain company names, job titles, posting URLs and counts. There are no candidate or recruiter details.

**Can my AI assistant use it?**
Yes. Apify exposes every Store Actor as a tool through its MCP server (mcp.apify.com), so Claude, Cursor and other assistants can call it.

### Related

- [Job Posting Parser](https://apify.com/keith-apis/job-posting-parser): turn job ad text into seniority, job function, remote regions, salary and skills.
- [Resume Parser + Job Match](https://apify.com/keith-apis/resume-parser-job-match): score a resume against a job posting.
- [keith-apis-mcp](https://github.com/Keithhk/keith-apis-mcp): an MCP server with job, resume and web page tools for AI assistants.

# Actor input Schema

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

company = one result per company (charged per company found); market = one market trend result; search = find the exact company name to use.

## `companies` (type: `array`):

Company names (case-insensitive). Up to 100 per run. Names that aren't found are skipped and not charged.

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

Part of a company name, e.g. 'grafana'.

## `weeks` (type: `integer`):

How many weeks back to include (max 104).

## `includeGhosts` (type: `boolean`):

List roles that look like ghost or evergreen postings, each with the reason.

## Actor input object example

```json
{
  "mode": "company",
  "companies": [
    "Stripe",
    "OpenAI",
    "Grafana Labs"
  ],
  "query": "graf",
  "weeks": 12,
  "includeGhosts": true
}
```

# 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 = {
    "companies": [
        "Stripe",
        "OpenAI",
        "Grafana Labs"
    ],
    "query": "graf",
    "weeks": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("keith-apis/remote-job-history").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 = {
    "companies": [
        "Stripe",
        "OpenAI",
        "Grafana Labs",
    ],
    "query": "graf",
    "weeks": 12,
}

# Run the Actor and wait for it to finish
run = client.actor("keith-apis/remote-job-history").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 '{
  "companies": [
    "Stripe",
    "OpenAI",
    "Grafana Labs"
  ],
  "query": "graf",
  "weeks": 12
}' |
apify call keith-apis/remote-job-history --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,keith-apis/remote-job-history"
        }
    }
}
```

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/FLajHgmblAD5u72xb/builds/BrCo0dYy69KoC6bMc/openapi.json
