# WordPress Post Scraper & Content Change Monitor (`vdb997/wordpress-content-watch`) Actor

Monitor public WordPress posts through the REST API. Export clean titles, excerpts, content and source URLs; detect new posts and content edits across runs. Persistent snapshots, keyword filters and one flat price per successful site check.

- **URL**: https://apify.com/vdb997/wordpress-content-watch.md
- **Developed by:** [Victor Diaz](https://apify.com/vdb997) (community)
- **Categories:** News, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 wordpress site checks

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

## WordPress Post Scraper & Content Change Monitor

Monitor WordPress blogs for new posts and meaningful content edits. Export clean titles, excerpts, body text, publication and modification timestamps, category/tag IDs and source URLs. Use it to keep a research database current, watch competitor publishing or refresh a content pipeline for AI analysis.

The Actor reads the public WordPress REST posts endpoint and compares normalized fields across runs. It distinguishes content changes from a timestamp-only update, avoiding alerts when WordPress marks a post modified but its exported content has not changed.

### Who this is for

**WordPress publishing research and content refresh.** Use the WordPress post scraper to maintain a research feed or refresh a content pipeline when public posts are newly observed or edited. It reads the WordPress REST API and compares exported content; it is not a crawler for arbitrary websites.

### Quick start

Extract current public posts:

```json
{
  "siteUrls": ["https://wordpress.org/news"],
  "maxPostsPerSite": 100,
  "includeContent": true,
  "outputMode": "all"
}
```

Monitor newly observed posts and edits:

```json
{
  "siteUrls": ["https://wordpress.org/news"],
  "maxPostsPerSite": 100,
  "watchId": "wordpress-updates",
  "outputMode": "changes",
  "includeContent": false
}
```

Use the WordPress installation URL. A subdirectory installation needs its subdirectory: `https://example.com/blog` reads `https://example.com/blog/wp-json/wp/v2/posts`. Do not paste a specific article, a query URL or the API endpoint itself. The Actor does not auto-discover nonstandard API roots.

### How change tracking works

The first successful changes-mode run establishes a baseline and emits a check summary. Later checks with the same Watch ID emit newly observed post IDs and changes to title, excerpt, plain-text body, URL, category IDs or tag IDs. `changedFields` tells you what differs. Body hashes are compared even when `includeContent=false`.

Posts are requested in descending modification order, up to your scan limit. This helps surface updates to older posts instead of looking only at their publication date. An old post entering the window for the first time is `new` to the watch, not necessarily newly published.

`titleKeywords` is an optional case-insensitive OR filter. It changes output only; all scanned posts are remembered. Changing keywords does not replay previously observed posts. Use a fresh Watch ID to intentionally establish a different baseline.

### Output

`recordType=post` records include:

| Field | Meaning |
| --- | --- |
| `postId`, `siteUrl`, `postUrl` | Post identity and public source |
| `title`, `excerpt`, `content` | Normalized plain text; body omitted when requested |
| `publishedAt`, `modifiedAt` | UTC timestamps from WordPress GMT fields, or null if absent/invalid |
| `categoryIds`, `tagIds` | Public taxonomy IDs, not fetched names |
| `changeType` | baseline, new, changed or unchanged |
| `changedFields`, `previousModifiedAt` | Changed normalized fields and previous observed modification time |
| `observedAt` | Time this Actor successfully checked the site |

A `check_summary` is always returned per successful site check with counts, pages checked, duplicate IDs skipped and a window-limit indicator. `source_error` records describe failures. The key-value store's `SUMMARY` records the overall result and spending-limit status.

### Pricing

**$0.05 per successful site check**, including up to 500 scanned posts and their change records, plus **$0.00005 per run start** at fixed 512 MB memory. Platform usage is included; no per-post or per-summary charge applies.

A successful empty or unchanged site still counts as a check. Unsupported sites or failed source requests do not trigger the site-check event. If a later pagination request fails, the entire site check fails without replacing history or billing its event. The standard start fee still applies.

Example: ten sites checked once cost $0.50005, or $15.0015 if run daily for 30 days. These are buyer costs, not developer earnings. Maximum cost per run is checked before starting each site.

### Scope and limits

- Reads public published posts through the standard WordPress REST API. It does not crawl full HTML pages, comments, private posts, user profiles, media libraries or WooCommerce products.
- Supports up to ten HTTPS sites and 1–500 posts per site, default 100. Pagination respects reported page totals and detects the normal end of an exact-size collection.
- Sites with disabled APIs, nonstandard API roots, protection pages, certificates that fail validation or private network addresses are unsupported. The Actor does not bypass those restrictions.
- Protected post bodies cause a failed check, preserving the previous snapshot rather than treating hidden content as an edit.
- Missing posts are not reported as deleted: this is a rolling window, and content can fall outside the scan range. Pagination is not an atomic snapshot and the source can change while it is being read.
- HTML layout changes that produce identical plain text do not trigger content alerts. This is a content monitor, not a visual page monitor.
- History keeps post IDs and field hashes for 90 days since last observation, with a 20,000-ID cap per site. Full historical bodies are not stored in the watch store. A new Watch ID resets history; use non-overlapping schedules for the same ID.

Source reference: [WordPress REST Posts API](https://developer.wordpress.org/rest-api/reference/posts/).

Related tools: [Google News Keyword Watch](https://apify.com/vdb997/google-news-keyword-watch), [App Store Review Watch](https://apify.com/vdb997/app-store-review-watch), and [ATS Job Watch](https://apify.com/vdb997/ats-job-watch).

### Try one source before scheduling

1. Open the Input tab and use one supported source with `outputMode: "all"` for an immediate export.
2. Check the returned records and the check summary. Confirm the source, coverage and price suit your workflow.
3. To monitor, set a stable Watch ID and `outputMode: "changes"`. The first successful run establishes a silent baseline.
4. Reuse that Watch ID on later runs. A summary without change records means the check completed without matching changes.
5. Add an Apify schedule after the manual checks work. Avoid overlapping runs with the same Watch ID. Use Maximum cost per run to cap event charges.

Public-data monitors by the same developer: [browse the catalog](https://apify.com/vdb997).

# Actor input Schema

## `siteUrls` (type: `array`):

Public WordPress installation URLs with HTTPS. Include the subdirectory for sites such as https://example.com/blog. The standard wp-json/wp/v2/posts endpoint must be available.

## `maxPostsPerSite` (type: `integer`):

Most recently modified posts, up to 500. This is a rolling window; posts outside it are not reported as deleted.

## `titleKeywords` (type: `array`):

Case-insensitive OR filter. Applied only to output after comparison; changing it does not reset the baseline.

## `includeContent` (type: `boolean`):

Turn off to omit body text from exported rows. Content edits are still detected.

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

Reuse an ID to keep snapshots in your account. Leave blank for a one-off extraction. Use a new ID to reset; do not run the same watch concurrently.

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

Changes mode establishes a silent baseline on the first run. Check summaries and source errors are always included.

## Actor input object example

```json
{
  "siteUrls": [
    "https://wordpress.org/news"
  ],
  "maxPostsPerSite": 100,
  "titleKeywords": [],
  "includeContent": true,
  "outputMode": "all"
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "siteUrls": [
        "https://wordpress.org/news"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vdb997/wordpress-content-watch").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 = { "siteUrls": ["https://wordpress.org/news"] }

# Run the Actor and wait for it to finish
run = client.actor("vdb997/wordpress-content-watch").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 '{
  "siteUrls": [
    "https://wordpress.org/news"
  ]
}' |
apify call vdb997/wordpress-content-watch --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vdb997/wordpress-content-watch"
        }
    }
}
```

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/QWtRXFseGVAcdf0YR/builds/dOjjne5C9UhjaJkGU/openapi.json
