WordPress Posts & Pages API — Any WP Site, No Login
Pricing
from $0.48 / 1,000 posts
WordPress Posts & Pages API — Any WP Site, No Login
Every WordPress site has a public JSON API; this reads it. Posts and pages from any WP site as clean rows: full text or Markdown, categories and tags by name, featured image, dates in UTC, word count. Free rows for sites that are not WordPress or have the API off. No login, no browser.
Pricing
from $0.48 / 1,000 posts
Rating
0.0
(0)
Developer
Insight Solutions
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Every WordPress site has a public JSON API; this reads it — no browser, no key, full text as Markdown. Give it any WordPress site and get its posts (and pages) back as clean rows: title, URL, publish and modified dates in UTC, excerpt, the whole body as plain text, Markdown or HTML, word count, categories and tags by name, featured image, format and sticky flag. Newest first, filtered by search, category, tag or date window, with a cap per site.
About four in ten websites run WordPress, and unless the owner has switched it
off, each one publishes its content at /wp-json/wp/v2/. This Actor reads that
API directly — the same data the site's own editor and apps use — instead of
scraping the HTML theme around it.
Why not scrape the pages? A theme wraps every post in navigation, sidebars, share buttons and comment forms that differ on every site. The REST API sends the post itself:
wordpress.org/newsanswered ten whole posts as 336 KB of JSON in 0.8 seconds, already split into title, dates, body, categories and image.
At a glance
Input — this is the Store prefill; paste it and run:
{ "sites": ["https://wordpress.org/news"], "contentTypes": ["posts"], "textFormat": "text", "maxItemsPerSite": 20 }
The twenty newest posts from the WordPress news blog, as plain text, plus one free row describing the site.
Output — one row per post or page; the fields you will use most are
title, url, publishedAt, text (or markdown), categories and
imageUrl (full list under Output reference). Every site that could not be
read — not WordPress, REST API switched off, blocked, rate-limited — comes back
as a free diagnostic row (rowType: "diagnostic", errorType, error)
instead of a charge.
Price — $0.80 per 1,000 posts on the FREE tier (+ $0.001 per run,
charged only once a run has returned a post or page). Site rows and diagnostic
rows are free, and a run that returns nothing bills nothing at all. Pay per
event, no API key, no browser, limited permissions — works over the Apify MCP
server (mcp.apify.com) and with agentic (x402) payments.
From code —
client.actor("insight.solutions/wordpress-posts-api").call(run_input={…})
with apify-client, or
POST https://api.apify.com/v2/acts/insight.solutions~wordpress-posts-api/run-sync-get-dataset-itemsWho it is for
- Content audits — every post on a site with its word count, categories, tags, publish and modified dates, in one table: find the thin posts, the stale ones and the categories nobody writes in any more.
- RAG corpora and AI training sets — whole bodies as Markdown, headings, lists, links and code blocks kept, one row per post with a stable URL and id.
- Competitor and industry blogs — what a set of companies published this
quarter (
publishedAfter), in which categories, at what length. - Migrations and backups — posts and pages with their HTML exactly as
WordPress rendered it (
textFormat: "html"), slugs, page tree (parentId,menuOrder) and featured images.
What you get
A post (abridged — the null columns and the end of the long strings are cut here; from wordpress.org/news):
{"ok": true,"rowType": "post","input": "https://wordpress.org/news","source": "wordpress.org","sourceUrl": "https://wordpress.org/news/wp-json/wp/v2/posts/21709","postId": 21709,"type": "post","title": "WordPress Takes Its Turn Leading the Open Website Alliance","url": "https://wordpress.org/news/2026/09/owa-president/","slug": "owa-president","publishedAt": "2026-09-21T14:28:41Z","modifiedAt": "2026-09-21T14:28:41Z","excerpt": "I’m happy to announce that I am now serving as president of the Open Website Alliance (OWA), representing the WordPress Foundation. …","text": "I’m happy to announce that I am now serving as president of the Open Website Alliance (OWA), representing the WordPress Foundation. The Alliance brings together…","wordCount": 239,"textTruncated": false,"contentProtected": false,"format": "standard","sticky": false,"categoryIds": [10],"tagIds": [648, 647],"featuredMediaId": 21712,"imageUrl": "https://i0.wp.com/wordpress.org/news/files/2026/09/image-3.png?fit=1600%2C900&ssl=1","commentStatus": "closed","author": null,"rank": 2}
Categories and tags come back by name as well as by id. From TechCrunch:
{"title": "OpenAI will start watermarking ChatGPT’s text in the EU","categories": ["AI", "Government & Policy"],"categorySlugs": ["artificial-intelligence", "government-policy"],"categoryIds": [577047203, 577065682, 17396]}
17396 was not in the categories answer this sample was built from, so it
stays in categoryIds and is left out of the names rather than guessed at.
With textFormat: "markdown" the body keeps its structure:
This security release features a fix for a critical severity security vulnerability.**Because this is a security release, it is recommended that you update your sites immediately.**You can [download WordPress 7.1.2 from WordPress.org](https://wordpress.org/download/), or visit your WordPress Dashboard, click “Updates”, and then click “Update Now”. …## Security update included in this release
And one free site row per WordPress site (from TechCrunch):
{"rowType": "site","siteName": "TechCrunch","siteUrl": "https://techcrunch.com","description": "Startup and Technology News","timezone": "America/Los_Angeles","wordpress": true,"restApi": "open","totalPosts": 262648,"returned": 20,"filteredOut": 0}
Quick start
- Put one or more sites in WordPress sites —
https://example.com,example.com/blog, or any post URL from the site. - Pick posts, pages or both, and a body format: plain text, Markdown, or the HTML as WordPress rendered it.
- Optionally narrow it: Search, Categories, Tags, Published after / before.
- Set Max items per site and run. Rows arrive newest first.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
sites | string[] | prefill ["https://wordpress.org/news"] | Site URLs, scheme optional. A subdirectory install (example.com/blog) is tried at its own path first, then at the host root. A pasted post, feed or /wp-json/ URL is read as the site it belongs to. Duplicates are dropped. |
contentTypes | string[] | ["posts"] | posts, pages, or both (in the order listed). |
search | string | "" | WordPress's own search (title, excerpt, content), sent to the list endpoint. Results stay newest first. |
categories / tags | string[] | [] | Ids, slugs (artificial-intelligence) or archive URLs (…/category/venture/). A slug is looked up once per site; a slug a site does not have is a free row. Pages have no categories or tags, so pages are skipped when one is set. |
publishedAfter / publishedBefore | string | — | 2026-09-01 or 2026-09-01T12:00:00. Sent as WordPress's after / before. A bare date is midnight at the start of that day. |
textFormat | select | text | text fills text; markdown fills markdown; html fills html with the body as WordPress rendered it. |
maxTextChars | integer | 50000 | Longer bodies are cut and textTruncated is set. wordCount always counts the whole post. |
includeFeaturedImage | boolean | true | Fills imageUrl and imageAlt: one extra request per page of up to 100 posts. |
maxItemsPerSite | integer | 50 (prefill 20) | 1–10,000. The most posts and pages, together, read from each site. |
maxConcurrency | integer | 3 | Sites in flight at once (1–10). |
maxRunSecs | integer | 240 | 30–3,600. Rows already returned are kept when it runs out. |
proxyConfiguration | object | { "useApifyProxy": true } | Apify datacenter proxy by default; switch to residential for sites that refuse datacenter addresses. |
A run with no usable site — nothing in sites, or nothing that parses as a
URL — or a date filter that is not a date finishes FAILED before a single
request, with a free row saying which entry was the problem. A date typo is
refused rather than ignored, so it can never turn a filtered run into an
unfiltered (and billed) one.
Output reference
Every row has the same columns, null where a column does not apply, so the
dataset exports as one table.
On every row: ok, rowType (post · page · site · diagnostic),
input, error, errorType, scrapedAt, source (the site's host),
sourceUrl (the REST URL behind the row).
Posts and pages:
| Column | What it is |
|---|---|
postId, type, slug, url | WordPress's id, type, slug and public URL. |
title | Plain text, entities decoded (Lucid Motors’ becomes Lucid Motors’). |
publishedAt, modifiedAt | UTC with a Z, from WordPress's date_gmt / modified_gmt. |
excerpt | One paragraph of plain text. WordPress's […] and a theme's "Continue reading →" link both end in a single …. |
text / markdown / html | The body, in the format you chose. Scripts, video players, embeds, lightbox buttons and icons are removed from text and markdown; html is untouched. |
wordCount, textTruncated | Words in the whole body; whether maxTextChars cut it. |
contentProtected | true for a password-protected post: the body and excerpt are then null (WordPress does not send them). |
format, sticky | Post format (standard, aside, video…) and whether the post is pinned. Posts only. |
categories, categorySlugs, categoryIds | Names, slugs and ids. An id the site does not return is kept in the ids and left out of the names. |
tags, tagSlugs, tagIds | The same for tags. |
featuredMediaId, imageUrl, imageAlt | The featured image. |
commentStatus | open or closed. Comments themselves are never read. |
parentId, menuOrder | Pages only: the page tree. |
author | Always null, by design — see below. |
siteName, rank | The site's name; 1 for its newest item, then 2, 3… |
Site rows (free, one per WordPress site): siteUrl, siteName,
description, timezone, wordpress (true), restApi (open ·
disabled · missing), totalPosts (the site's own post count), totalWpPages
(its page count, when pages were asked for), returned (rows this run
delivered from it) and filteredOut (how many of its posts your filters
excluded — one extra tiny request, only when a filter is set).
Diagnostic rows (free):
errorType | Meaning |
|---|---|
invalid-input | An entry that is not a URL, a category or tag slug the site does not have, a filter WordPress refused, or pages asked for with a category filter. |
not-wordpress | No REST API index at /wp-json/ or ?rest_route=/, or one without the core wp/v2 API. |
rest-disabled | WordPress answered but refuses its API to visitors (401/403, rest_login_required, rest_forbidden), or has removed the posts route (rest_no_route). Also a 403 page that WordPress itself served. |
blocked | A 403 or a bot-protection page, twice, from two exit IPs. |
rate-limited | HTTP 429, twice, from two exit IPs. |
http, timeout | Any other failure, and a site that did not answer in time. |
deadline | The run's time budget ran out while a site was being read, or before it started. Rows already returned are kept. |
no-posts | The site publishes none, or none match your filters. |
internal | This Actor's own error. The run is then FAILED. |
How a site is read
For each site, at most five kinds of request, never one per post:
GET /wp-json/?_fields=name,description,…,namespaces— is this WordPress, and is itswp/v2API on. Asked with_fields, because the full index is 798 KB on TechCrunch (636 routes).GET /wp/v2/posts?per_page=…&orderby=date&order=desc&_fields=…— the rows, up to 100 per request, paged withx-wp-total,x-wp-totalpagesandLink: rel="next".GET /wp/v2/media?include=<ids>— featured images, one request per page of posts. When a site does not return an attachment there, the post's own Jetpack image URL is used.GET /wp/v2/categories?include=<ids>and/wp/v2/tags?include=<ids>— names, cached for the site, so an id is looked up once per run.- Only with a filter: one
per_page=1request for the site's unfiltered total.
_embed is never used: on TechCrunch it turned ten posts into 13 MB.
Each site gets at most two requests in flight, 300–600 ms apart, through its
own proxy session, however many sites run at once. Every request carries a
User-Agent naming this Actor, so a site owner can see what read their API.
Bylines are not included, by design. WordPress author names are personal
data. This Actor never requests the author field, never calls
/wp/v2/users and never reads comments, so no row can carry a byline or a
commenter. The author column exists so you can see that, and it is null on
every row.
Reading 1,000 posts of a news site with text and images is about 10 list requests, 10 media requests and a handful of term requests (only ids not seen on an earlier page are looked up).
What you are never charged for
- Every
siterow. - Every
diagnosticrow: sites that are not WordPress, REST APIs that are switched off, blocked or rate-limited requests, timeouts, slugs that do not exist, filters that match nothing. - Posts your filters exclude — WordPress applies them before anything is downloaded.
- A post that moves onto the next page while the walk is under way (it is dropped before it can be counted twice).
- A second
sitesentry that turns out to be the same install as an earlier one — two post URLs from one blog, say. It is read once, and the second entry gets a free row saying so. - A run that returns nothing at all: it finishes SUCCEEDED with zero results and a "0 results … Nothing was charged." status message, and bills nothing, start fee included.
Password-protected posts are still post rows (title, URL, dates, categories)
and are billed as posts; their body is null because WordPress does not send it.
Pricing
| Event | What it is | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|---|
actor-start | Charged once per run, only after the run has returned a post or page | $0.001 | $0.001 | $0.001 | $0.001 |
post | One post row | $0.0008 | $0.0008 | $0.00064 | $0.00048 |
page | One page row | $0.0008 | $0.0008 | $0.00064 | $0.00048 |
$0.80 per 1,000 posts.
| Run | Cost |
|---|---|
| The default input — 20 posts from one site | $0.017 |
| The last 1,000 posts of a news site, with text and images | $0.801 |
| The same 1,000 posts at GOLD | $0.481 |
| 50 competitor blogs, 20 posts each | $0.801 |
| A list of sites none of which is WordPress | $0.00 |
Charging is charge-after-push: rows are in your dataset before the event is
recorded. ACTOR_MAX_TOTAL_CHARGE_USD is respected — the run stops fetching
when it is reached and finishes SUCCEEDED saying so.
Proxy
The default is { "useApifyProxy": true } — Apify's datacenter pool. The
capture probe read wordpress.org, TechCrunch and ma.tt through it. Some sites
put their API behind a firewall that refuses datacenter addresses; for those,
switch proxyConfiguration to residential. A 403 or 429 is treated as a block:
that site's proxy session is rotated once, and a second refusal becomes a free
blocked or rate-limited row rather than a retry loop. A 403 that WordPress
itself served (a JSON rest_forbidden, or the site's own themed error page) is
reported as rest-disabled — asking again from another address would not
change the answer.
Use it from an AI agent, or from code
One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~wordpress-posts-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"sites":["https://wordpress.org/news"],"textFormat":"markdown","publishedAfter":"2026-09-01","maxItemsPerSite":100}'
# pip install apify-clientfrom apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("insight.solutions/wordpress-posts-api").call(run_input={"sites": ["https://wordpress.org/news", "https://ma.tt"],"textFormat": "markdown","maxItemsPerSite": 200,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():if row["rowType"] == "post":print(row["publishedAt"], row["siteName"], row["title"], row["wordCount"], row["url"], sep=" | ")elif row["rowType"] == "diagnostic":print("could not read", row["input"], row["errorType"], row["error"])
FAQ
Do I need an account on the site, or an API key? No. Only what each site publishes to anonymous visitors is read.
What if a site has switched its REST API off? You get one free
rest-disabled row for it and nothing is billed. A plugin that locks the API
answers with a 401 or 403 and a rest_… error code; some sites answer with
their own themed 403 page instead — both are recognised.
How do I know a site is not WordPress? It costs two or three tiny requests
and returns one free not-wordpress row naming every address that was tried.
Why are some category names missing when the ids are there? The site did
not return that term from its categories endpoint (it may be hidden or
deleted). The id is kept in categoryIds so nothing is silently lost.
Can I get custom post types (products, events, case studies)? Not yet: this
Actor reads posts and pages. Custom types live at their own routes and
differ on every site.
Does publishedAfter use UTC? WordPress compares the value with each
post's publish time in the site's own timezone, so a bare date means
midnight on the site's clock. publishedAt on every row is UTC.
How many posts can I get from one site? Up to 10,000 per run
(maxItemsPerSite), read 100 at a time.
Limitations
- Sites that disabled the REST API cannot be read. That is the owner's choice; you get a free row saying so. This Actor never falls back to scraping the HTML theme.
- Bylines are not included, by design (see How a site is read).
- Only
postsandpages; no custom post types, comments or users. - Featured-image alt text comes from the media endpoint; when a site does not
return an attachment there, the image URL comes from the post's Jetpack field
and
imageAltisnull. publishedAfter/publishedBeforefollow WordPress's own comparison in the site's timezone.- A site's plugins can change what its API returns. The upstream format may
change: this Actor reads WordPress core's documented fields and leaves a
column
nullwhen a site does not send it, rather than failing the row. - Not affiliated with WordPress, the WordPress Foundation or Automattic. "WordPress" is used only to say which software's public API is read.
Related: for any site, WordPress or not, read from its HTML, use Website to Markdown — Content Extractor for LLMs & RAG. To get only the new posts of a blog on a schedule, use RSS & Atom Feed Monitor — every WordPress site also publishes a feed.
Our other Actors
Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.
Video, audio & social
- YouTube Transcript API — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- YouTube Comments API — comments and replies with likes, pinned and hearted flags, newest or top sort.
- YouTube Channel API — a channel's videos, Shorts and live streams, plus YouTube search.
- Podcast Search, Episodes & Charts API — Apple Podcasts search, charts and full episode feeds.
- Bluesky Scraper — profiles, posts, followers and follows from the public AT Protocol API.
- Telegram Channel Scraper — posts, views and channel stats from public Telegram channels.
- Substack Scraper — posts with full free text, comments and publication profiles.
- Hacker News API — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.
- GitHub Repos, Trending & Releases API — repository facts, trending lists, releases and search, no token needed for small runs.
- Discourse Forum API — topics, posts and categories from any Discourse community via its own JSON endpoints, usernames only.
News, documents & the web
- Google News Search, Topics & Real Article URLs — news search and topic feeds with the publisher's real URL decoded.
- Website to Markdown — Content Extractor for LLMs & RAG — any site as clean Markdown, text and heading-aware chunks.
- Website Metadata API — any URL's meta tags, Open Graph, Twitter cards, hreflang, feeds, JSON-LD and microdata, with normalised Product, Article, Event and FAQ entities.
- Subdomain Finder API — every subdomain of a domain from certificate-transparency logs, resolved over DNS, with an optional live HTTP check.
- Internet Archive API — archive.org search, item metadata, files and reviews.
- Wayback Machine Toolkit — archived URL inventories, snapshots and text diffs between dates.
- Website Technology Detector — the tech stack behind any site, with the evidence for each detection.
- Domain Intelligence API — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- SEO Page Audit — sitemap crawl with on-page checks, structured data and broken-link reports.
- Keyword Suggestions API — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- Website Contact Extractor — emails, phone numbers and social profiles from any list of websites.
- Web Search Results API — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- Company Enrichment API — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.
- Company Dossier API — one company in, twelve sections out: profile, tech, contacts, DNS, open roles, news, SEC filings, federal awards, recalls, YC batch and apps.
- Press Releases API — GlobeNewswire and PR Newswire releases plus any newsroom feed, by keyword, company, ticker or subject.
- Federal Register API — rules, proposed rules, notices and the Public Inspection desk with dockets, comment deadlines and CFR references.
- Academic Papers Search API — OpenAlex, Crossref, arXiv and PubMed in one row per paper: abstract, citations, open-access PDF, authors and venue.
- RSS & Atom Feed Monitor — any RSS, Atom or JSON feed (or an OPML file) in, only the new items out, with keyword filters and a webhook.
- Website Change Monitor — watch any pages, diff the text between runs, get change rows with added/removed lines, keyword alerts and a webhook.
- Wikipedia & Wikidata API — article text, search, daily pageviews and Wikidata entity facts, any language edition.
Business, finance & jobs
- Congress & Insider Trades API — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- Federal Contracts, Grants & Lobbying API — SAM.gov opportunities, USAspending awards, Grants.gov notices and Senate lobbying filings in one schema.
- SEC EDGAR API — filings, XBRL financials and full-text search by ticker or CIK.
- Clinical Trials & FDA API — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- Product & Vehicle Recalls API — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- Y Combinator Companies, Batches & Founders — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- Career Site Jobs API — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- Workday Jobs API — every posting on any Workday career site, with facets, search, posted dates and full descriptions.
- New Job Postings Monitor — new, closed and changed postings on the career sites you watch.
- Hiring Signals API — Open Roles & Hiring Surge by Company — one row per company per run: open roles, what opened and closed, department and seniority breakdowns, and a hiring-surge flag.
- Remote Jobs API — RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy and more in one schema, deduplicated.
- Shopify Products API — any Shopify store's catalogue, variants, prices and stock signals.
- WooCommerce Products API — any WooCommerce store's catalogue, prices, variants and stock through its public Store API.
- Shopify App Store API — Shopify App Store listings by category, collection or developer: pricing plans, ratings and merchant reviews.
- Luma Events API — upcoming Luma events by city, category or calendar: dates, venue, price, capacity and organiser calendar, no host names.
- Shopify Store Monitor — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.
- Public Tenders API — EU TED, UK Find a Tender and Contracts Finder notices by keyword, CPV code, country, stage and deadline.
- Nonprofit & IRS 990 Lookup API — search US nonprofits and get EIN, NTEE code and multi-year Form 990 financials.
- OpenStreetMap Places API — businesses and points of interest by category and area from OpenStreetMap: name, address, coordinates, website, phone, opening hours.
Apps & games
- App Store & Google Play Reviews API — reviews from both stores with ratings, versions and developer replies.
- App Store Top Charts & App Search API — Apple top charts by country and genre, plus app search and details.
- App Store Keyword Rank Tracker — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- Steam Reviews API — Steam reviews with playtime, helpfulness and game details.
- Steam Game Data API — prices, tags, review scores, live player counts and top charts.
- Sports Scores & Schedules API — scores, schedules, standings, teams and headlines for the NFL, NBA, MLB, NHL, soccer and more, no key.
- App Store Monitor — App Store and Google Play listings watched between runs: new versions with release notes, price, rating and listing changes, one row per change.