# LinkedIn Keyword Post Monitor — New Posts & Request Signals (`agency-shift/linkedin-keyword-post-monitor`) Actor

Monitor LinkedIn keyword searches for newly observed posts. Export source links, exact phrase evidence and request-language signals with persistent deduplication. Uses separately billed HarvestAPI collection, or process an existing dataset without a new source run.

- **URL**: https://apify.com/agency-shift/linkedin-keyword-post-monitor.md
- **Developed by:** [Mako](https://apify.com/agency-shift) (community)
- **Categories:** Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.98 / 1,000 delivered qualifying posts

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## LinkedIn Keyword Post Monitor

Find newly observed LinkedIn posts about your selected topics, keep the original source text and links, and avoid processing the same qualifying posts on every scan. Useful for GTM research, niche content discovery and finding questions worth answering.

**Live collection uses the separately billed [HarvestAPI LinkedIn Post Search](https://apify.com/harvestapi/linkedin-post-search). This Actor adds filtering, evidence and persistent monitoring; it is not an independent LinkedIn extraction engine.** Existing-dataset mode processes posts you have already collected without starting another source run. No LinkedIn password, session cookies or developer-owned API key are included or requested.

Live mode requires an Apify plan that permits running public Store Actors. Some Creator plans restrict this; those accounts can use existing-dataset mode. The Actor does not change your subscription or silently use another account.

### Quick start

```json
{
  "sourceMode": "search",
  "queries": ["\"CRM migration\""],
  "postedLimit": "week",
  "sortBy": "date",
  "mode": "new",
  "monitorName": "crm-questions",
  "requestsOnly": true,
  "maxScanPosts": 25,
  "maxResults": 25,
  "maxSourceChargeUsd": 0.1,
  "sourceTimeoutSecs": 180
}
```

Run again with the same monitor name and search/filter settings to receive newly observed qualifying posts. Add an Apify schedule yourself if you want recurring scans; this Actor does not silently create schedules or publish comments.

`requestsOnly` uses simple English phrases and question punctuation. It can match rhetorical or promotional questions. Read the actual evidence before responding. Neither a matching term nor a question proves someone wants to buy your product.

For existing data, select **Existing Apify dataset** and enter a dataset ID in `sourceDatasetId`. The supported row shape includes `id`, `linkedinUrl`, `content`, optional `author`, `postedAt` and `engagement`. Source errors, non-post records and missing identities/text are not treated as valid posts. Dataset mode reads the first `maxScanPosts` rows; increase that cap to examine more rows. Search time-window options are not reapplied to existing datasets.

### What you receive

- Original available post text, source URL and identity.
- Source publication date and author fields when available; unknown values stay null.
- Available engagement counts, without adding overlapping likes and reaction totals.
- Exact matched phrase text and character offsets, plus explicit request-language rule labels.
- A stable `eventId`, source-run IDs and field provenance.
- A separate `SUMMARY` containing coverage, source work, costs when available, pending output and errors.

Output is JSON and can be exported through Apify as CSV or Excel. Large nested fields remain available in JSON.

### Prices and spending controls

Our monitoring fee is **$1.98 per 1,000 delivered post records**, plus a $0.00005 startup event per allocated GB of memory (minimum one event). Apify compute and storage usage are separate.

Live searches also pay HarvestAPI on the running customer's Apify account. On 1 October 2026 its base Free/Starter price was **$2 per 1,000 collected posts**, with tier discounts; an empty query can also incur a source event. Check the [current source pricing](https://apify.com/harvestapi/linkedin-post-search/pricing). Profile enrichment, comments and reactions collection are disabled in our source input.

For example, collecting 100 posts and delivering 20 qualifying posts costs approximately **$0.20 source fees + $0.0396 monitoring fees**, plus applicable startup/platform costs. This is an illustration, not an all-in quote. Filtered-out posts and previously seen posts can still incur upstream collection charges. A run producing zero new posts can still cost money.

- `maxScanPosts` caps requested source posts across all queries; each query receives `floor(maxScanPosts / queryCount)`.
- `maxResults` caps our delivered output; it does not cap the cost of collecting candidates.
- `maxSourceChargeUsd` is the separate child-run PPE ceiling. It is not the parent Actor or total account budget.
- Apify's maximum Actor charge controls our event fees, not every source/platform charge.
- `sourceTimeoutSecs` bounds collection and is reduced when the parent has less time remaining.

### Monitoring behavior

The first new-post scan emits matching observations by default. Set `emitInitial: false` to seed a qualifying baseline without output fees. Later observations are compared with that saved baseline. Changes to reaction counts do not generate new-post events.

Queries, source selection, time window, ordering and filters are part of the history scope. Changing them creates a separate baseline. Changing `maxResults` does not reset history. Keep `monitorName` stable; change it deliberately to start fresh. History belongs to the running user and Actor.

Qualified overflow is saved before delivery. The next run drains that pending output before collecting new data. A monitor lock prevents simultaneous writers. If a crash occurs after output but before its checkpoint is saved, an event can be delivered and charged again with the same `eventId`; consumers should deduplicate this ID. Delivery is at least once, not exactly once.

History does not silently expire. It stops at the configured item limit or 16 MB size limit rather than forgetting identities and unexpectedly repeating old posts.

### Coverage and troubleshooting

This is a bounded observation workflow. Search results can be ranked, incomplete, delayed or restricted by the source. “New” means newly observed in this monitor, not proof that a post was just published. Missing posts never generate deletion events. This Actor cannot promise all LinkedIn posts, global virality or private analytics.

Failed or partial source runs do not establish an empty baseline. Inspect `SUMMARY` and `ERROR`. `SOURCE_RUN` records source launch information; an uncertain launch is not automatically retried, preventing an accidental second charge inside the same parent run. Existing-dataset mode can be used to process a completed compatible source dataset.

Source access, platform permissions and pricing can change. The Actor fails before collection if the configured source no longer supports the expected limited-permission, pay-per-event contract.

# Actor input Schema

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

Live search uses paid HarvestAPI collection on your account. Existing dataset mode processes data you already collected and starts no new scraper.

## `queries` (type: `array`):

One to five keyword or Boolean queries. Required for live search. Search is provided by HarvestAPI; matching a query is not proof of buying intent.

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

Required only in dataset mode. An Apify dataset containing compatible LinkedIn post rows. Only read permission is requested.

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

Live-search filter passed to the source. Dataset mode preserves the supplied data and does not independently enforce this time window.

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

Newest first is usually useful for monitoring. This controls source selection, not a guarantee of complete LinkedIn coverage.

## `includePhrases` (type: `array`):

Optional case-insensitive literal substring rules applied after collection. Output includes exact matched text and offsets. Collection charges apply before filtering.

## `excludePhrases` (type: `array`):

Optional case-insensitive literal exclusions. Excluded posts are not charged our post-record fee; source fees still apply.

## `requestsOnly` (type: `boolean`):

Uses simple English phrase rules and question punctuation, not AI or verified purchase intent. Rhetorical and promotional questions can still match; review the supplied evidence.

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

New posts remembers delivered identities across runs. Snapshot emits the observed qualifying posts each scan. Neither mode infers deleted posts or complete source coverage.

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

Reuse a name for recurring scans. Query, source and filter changes create a separate baseline. A new name deliberately creates new history.

## `emitInitial` (type: `boolean`):

Disable to save the initial qualifying baseline without post-record fees. Live-source and platform costs still apply.

## `maxScanPosts` (type: `integer`):

Shared cap across all queries. For live search each query receives floor(cap/query count), so the total requested never exceeds this cap. Repeats and excluded source posts count toward source work.

## `maxResults` (type: `integer`):

Caps this monitor output. Qualified overflow is saved for the next run before another source scan. Changing this cap does not reset history.

## `maxSourceChargeUsd` (type: `number`):

Separate child-run PPE ceiling, not a total account or parent-platform budget. A source run reaching its limit can stop with incomplete data. No automatic source retries or enrichment.

## `sourceTimeoutSecs` (type: `integer`):

Live source timeout is also constrained by the parent time remaining. A failed source does not establish an empty baseline.

## `maxHistoryItems` (type: `integer`):

History never silently expires or evicts records. At the count or 16 MB size limit, the monitor stops and asks for a new monitor or a higher supported count.

## Actor input object example

```json
{
  "sourceMode": "search",
  "queries": [
    "\"CRM migration\""
  ],
  "postedLimit": "week",
  "sortBy": "date",
  "includePhrases": [],
  "excludePhrases": [],
  "requestsOnly": false,
  "mode": "new",
  "monitorName": "default",
  "emitInitial": true,
  "maxScanPosts": 50,
  "maxResults": 25,
  "maxSourceChargeUsd": 0.1,
  "sourceTimeoutSecs": 180,
  "maxHistoryItems": 20000
}
```

# Actor output Schema

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

No description

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

No description

## `error` (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 = {
    "queries": [
        "\"CRM migration\""
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("agency-shift/linkedin-keyword-post-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 = { "queries": ["\"CRM migration\""] }

# Run the Actor and wait for it to finish
run = client.actor("agency-shift/linkedin-keyword-post-monitor").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 '{
  "queries": [
    "\\"CRM migration\\""
  ]
}' |
apify call agency-shift/linkedin-keyword-post-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,agency-shift/linkedin-keyword-post-monitor"
        }
    }
}
```

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/cRePS8xIYysdU88QK/builds/8XObdgwnD6r1tup3R/openapi.json
