WordPress Content Exporter - posts & pages to JSON/Markdown avatar

WordPress Content Exporter - posts & pages to JSON/Markdown

Pricing

from $1.20 / 1,000 post or page exporteds

Go to Apify Store
WordPress Content Exporter - posts & pages to JSON/Markdown

WordPress Content Exporter - posts & pages to JSON/Markdown

Export posts, pages, custom post types, categories, tags, authors and media metadata from any public WordPress site via the REST API. Clean HTML, Markdown and plain text per post, incremental sync since last run, sitemap/RSS fallback when the API is disabled.

Pricing

from $1.20 / 1,000 post or page exporteds

Rating

0.0

(0)

Developer

WEIGUO HAN

WEIGUO HAN

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 days ago

Last modified

Categories

Security

Limited permissions

Share

WordPress Content Exporter - export posts & pages to JSON, Markdown and plain text (REST API, no plugin)

Export every public post, page and custom post type from any WordPress site in one run - no plugin to install, no login, no API key. Give the Actor a site URL; it finds the site's WordPress REST API (/wp-json/wp/v2/), walks all pages of results and returns clean, structured items: title, slug, URL, excerpt, content as HTML, Markdown and plain text, word count, author, categories, tags, featured image (URL + alt text), published/modified dates and language. Categories, tags, authors and media-library metadata can be exported too.

Built for RAG / LLM knowledge bases, content migration, backups, SEO audits, competitor blog monitoring and news aggregation. Run it on a schedule with sinceLastRun and it only exports (and only charges for) what changed.

Pricing: $1.50 per 1,000 posts + $0.02 per site (pay per event, see below). Taxonomy, author and media items are free.

Why this WordPress scraper

What this Actor delivers (facts checked 2026-10-16):

This Actor
Data sourceWordPress REST API (structured JSON straight from the CMS); no browser, no plugin, no login
Content formatsHTML + Markdown + plain text, word count, reading time
Coverageposts, pages, any custom post type (product, docs, ...), categories, tags, authors, media metadata
Price$1.50 per 1,000 posts + $0.02 per site; category, tag, author and media items, skipped unmodified items and failed sites are free
Incremental syncmodifiedAfter + sinceLastRun cursor in a key-value store
REST API disabled?Automatic fallback: sitemap / RSS discovery + article extraction
Speed100 posts per request, pure HTTP, 256 MB memory
Politeness<= 2 requests/s per host, exponential backoff, Retry-After, automatic slow-down after a 429, robots.txt

How to export WordPress content (tutorial)

  1. Open the Actor and paste one or more WordPress site URLs - the homepage (https://example.com), a blog in a sub-directory (https://wordpress.org/news) or any page of the site. The API root is discovered automatically (<link rel="https://api.w.org/">, /wp-json/, or /?rest_route=/ for sites with plain permalinks).
  2. Pick Post types (post, page by default; add product, portfolio, ... or all) and optionally Max items per site, a Search phrase or Modified after.
  3. Turn on Export categories and tags / authors / media metadata if you need them (free).
  4. For recurring exports enable Only content changed since the last run and schedule the Actor.
  5. Click Start. Results land in the dataset (table / JSON / CSV / Excel / API); a per-site summary with the source used and any warnings is stored under the SUMMARY key of the run's key-value store.

Input example

{
"startUrls": [
{ "url": "https://wordpress.org/news" },
{ "url": "https://wptavern.com" }
],
"postTypes": ["post", "page"],
"maxItemsPerSite": 500,
"includeContentMarkdown": true,
"includeTaxonomies": true,
"sinceLastRun": true
}

Output example (one dataset item per post / page)

Recorded from https://wordpress.org/news (content fields shortened):

{
"id": 21753,
"type": "post",
"siteUrl": "https://wordpress.org/news",
"siteName": "WordPress News",
"url": "https://wordpress.org/news/2026/10/wordpress-7-1-3-maintenance-and-security-release/",
"slug": "wordpress-7-1-3-maintenance-and-security-release",
"title": "WordPress 7.1.3 Maintenance and Security Release",
"status": "publish",
"excerptHtml": "<p>This security and maintenance release features 7 security fixes and 4 bug fixes. ...</p>",
"excerptText": "This security and maintenance release features 7 security fixes and 4 bug fixes. ...",
"contentHtml": "<p class=\"wp-block-paragraph\">This security and maintenance release features 7 security fixes and <a href=\"https://core.trac.wordpress.org/query?milestone=7.1.3...\">4 bug fixes</a>.</p> ...",
"contentMarkdown": "This security and maintenance release features 7 security fixes and [4 bug fixes](https://core.trac.wordpress.org/query?milestone=7.1.3...).
**Because this is a security release, it is recommended that you update your sites immediately.**
## Security updates included in this release
- ...",
"contentText": "This security and maintenance release features 7 security fixes and 4 bug fixes.
Because this is a security release, it is recommended that you update your sites immediately. ...",
"wordCount": 400,
"readingTimeMinutes": 2,
"authorId": 1182764,
"authorName": "Jake Spurlock",
"authorSlug": "whyisjake",
"authorUrl": "https://profiles.wordpress.org/whyisjake/",
"categories": [
{ "id": 14, "name": "Releases", "slug": "releases", "taxonomy": "category", "url": "https://wordpress.org/news/category/releases/" },
{ "id": 15, "name": "Security", "slug": "security", "taxonomy": "category", "url": "https://wordpress.org/news/category/security/" }
],
"tags": [],
"otherTerms": [],
"categoryNames": ["Releases", "Security"],
"tagNames": [],
"featuredImageId": null,
"featuredImageUrl": null,
"featuredImageAlt": null,
"publishedAt": "2026-10-06T17:00:00Z",
"modifiedAt": "2026-10-07T08:07:00Z",
"language": "en-US",
"format": "standard",
"parentId": null,
"menuOrder": null,
"sticky": false,
"commentStatus": "closed",
"commentCount": null,
"source": "rest",
"scrapedAt": "2026-10-07T09:12:44Z"
}

featuredImageUrl / featuredImageAlt are filled when the post has a featured image (this one has none); otherTerms holds custom-taxonomy terms (e.g. WooCommerce product categories). Items from the HTML fallback have the same shape with source: "html".

With includeRaw: true the untouched REST object (including _embedded and Yoast SEO metadata when the site exposes it) is attached under raw.

Extra items share the same dataset and are distinguished by type:

{ "type": "category", "id": 3, "name": "Community", "slug": "community", "description": null, "count": 113, "parentId": null, "url": "https://wordpress.org/news/category/community/", "siteUrl": "https://wordpress.org/news" }
{ "type": "author", "id": 1182764, "name": "Jake Spurlock", "slug": "whyisjake", "description": null, "website": "https://profiles.wordpress.org/whyisjake/", "avatarUrl": "https://secure.gravatar.com/avatar/...", "url": "https://profiles.wordpress.org/whyisjake/", "siteUrl": "https://wordpress.org/news" }
{ "type": "media", "id": 180512, "url": "https://wptavern.com/wp-content/uploads/2026/10/example.png", "altText": "Screenshot of the block editor", "caption": null, "mediaType": "image", "mimeType": "image/png", "width": 1600, "height": 900, "attachedToPostId": 180500, "publishedAt": "2026-10-06T16:40:11Z", "siteUrl": "https://wptavern.com" }

Use the dataset views Posts & pages, Content (Markdown) and Categories, tags, authors, media in the Output tab, or filter by type through the API.

Incremental sync - only new and updated posts

  • modifiedAfter - export only content modified after a date/time (sent to the API as modified_after and verified client-side, so it also works on WordPress < 5.7).
  • sinceLastRun - the Actor remembers the newest modifiedAt per site in the named key-value store stateStoreName (default wordpress-content-export-state) and continues from there next time. The first run exports everything.
  • Sync runs (either option set) walk each site oldest-modified to newest (orderby=modified&order=asc), so the cursor can always advance safely - even when a run is capped by maxItemsPerSite or stopped by your charge limit, everything unseen is newer than the cursor and is picked up next time. That also lets you spread a huge initial sync over several runs. The cursor is not advanced for a site whose listing failed with an error, so nothing is skipped.
  • Combine both: modifiedAfter sets a floor, sinceLastRun keeps moving forward. Plain exports (neither option) list newest-first, which is what you want with maxItemsPerSite.

Schedule the Actor daily, connect a webhook or an integration (Google Sheets, Make, n8n, Zapier, Airbyte, your vector database) and you have a live mirror of any WordPress site.

When the REST API is disabled (fallback mode)

Some sites turn the REST API off (plugins such as "Disable REST API", returning 401 rest_authorization_required / 403) or hide it behind a CDN. With mode: auto the Actor then:

  1. lists URLs from the site's XML sitemaps (Sitemap: lines in robots.txt, /wp-sitemap.xml, Yoast/RankMath sitemap_index.xml, post-sitemap.xml, ...) - keeping only post/page sitemaps and skipping category/tag/author maps; if no sitemap exists it reads the RSS feed (/feed/, newest 10-50 posts),
  2. fetches each page and extracts the article with WordPress theme conventions: .entry-content / articleBody, rel="category tag" links, <link rel="shortlink" href="?p=ID">, postid-123 body classes, Open Graph and JSON-LD metadata.

Items from this path carry source: "html". Expect small gaps (see Limitations). Force the path with mode: html when a site's API returns truncated content; use mode: rest to skip sites without an API.

Pricing (pay per event)

EventWhat it meansPrice
postOne post, page or custom-post-type item written to the dataset (HTML + Markdown + text)$0.0015 ($1.50 / 1,000 posts)
site-crawledOne site whose REST API or sitemap/RSS was successfully discovered in a run$0.02 per site per run
Actor startApify's standard synthetic start event at the platform defaultplatform default

Category, tag, author and media items, skipped unmodified items, unreachable or blocked sites and failed pages are never charged. Proposed volume discounts for higher Apify plans: post $0.0012 (Silver) / $0.0010 (Gold).

Cost examples

  • One-off export of a 2,000-post blog with Markdown and taxonomies: 2,000 x $0.0015 + $0.02 = $3.02.
  • Daily sync of 20 competitor blogs with sinceLastRun, ~60 changed posts per day: 60 x $0.0015 + 20 x $0.02 = $0.49 per day.
  • Migrating 50 client sites with 500 posts each (25,000 posts): $37.50 + $1.00 = $38.50.

Use cases

  • RAG / AI knowledge bases - Markdown per post with headings, links and code blocks preserved; wordCount for chunking; modifiedAt for re-indexing only what changed.
  • Content migration & backups - move a blog to Hugo, Astro, Ghost, Notion or another WordPress; keep slugs, dates, authors and taxonomies.
  • SEO & content audits - word counts, publish cadence, authors, categories, missing featured images or alt texts across whole sites.
  • Competitor & industry monitoring - scheduled incremental exports of other blogs into Google Sheets, Slack or your CRM.
  • News & research datasets - clean article text with dates and authors from thousands of WordPress-powered newsrooms.
  • AI agents / MCP - "summarize everything example.com published this month" becomes one Actor call.

Limitations and good-to-know

  • Public content only. The Actor never authenticates, so only published, non-password-protected content is exported (password-protected posts appear with metadata but no body). Drafts, private posts and members-only content are out of scope by design.
  • Some sites restrict endpoints. The /users endpoint is frequently hidden (401); authors are still available inside each post through _embed. Custom types must be exposed to the REST API by the site (show_in_rest).
  • Fallback mode is heuristic. Without the API, IDs come from shortlinks/body classes (may be missing), excerpts from meta descriptions, tags from rel="tag" links, and the content container is picked by theme conventions - unusual themes can include related-post boxes or miss sidebars. RSS feeds only list the most recent posts. Taxonomy/author/media lists are REST-only.
  • CDN / bot protection. A few sites answer 403 to datacenter IPs. The Actor stops on persistent 401/403/429 and reports it in SUMMARY; try the proxyConfiguration input (Apify Proxy) for those sites. The Actor does not bypass CAPTCHAs, logins or paywalls.
  • Politeness limits throughput. At most 2 requests per second per site, halved every time a site answers 429 (down to one request per 10 s): a 10,000-post site takes ~1 minute through the API (100 posts per request) but ~1.5 hours in fallback mode (one page per post). includeTaxonomies on a site with thousands of tags adds one request per 100 terms.
  • Dates are normalized to UTC ISO-8601 from date_gmt / modified_gmt. language comes from Polylang/WPML fields when present, otherwise from the site's <html lang>.
  • You are responsible for having the right to use the exported content; the Actor honours each site's robots.txt and Retry-After headers.

FAQ

Does this work on any WordPress site? Yes for any public site with the REST API enabled (the WordPress default since 4.7, including WordPress.com and WordPress VIP sites). Sites that disabled the API go through the sitemap/RSS fallback.

Do I need to install a plugin on my WordPress site? No. Everything is read through public endpoints - which also makes it a good way to export a site you do not administer (with permission).

Can I export WooCommerce products or other custom post types? Yes - add the type's name (product, docs, portfolio) to postTypes or use all; the Actor reads /wp/v2/types to find the right route. WooCommerce product data (prices, stock) lives in a separate authenticated API and is not included.

How do I get only new or updated posts? Set sinceLastRun: true and run on a schedule, or pass modifiedAfter.

Why is authorName empty? The site hides the users endpoint and does not embed authors. Fallback-mode items use byline / JSON-LD / meta author tags.

Does it download images or media files? No - media export returns URLs and metadata only (fast and cheap). Pipe the URLs to a downloader if you need the files.

Can it run locally? Yes: apify run with the Apify CLI, or python -m src inside a venv. Unit tests: pytest.

Changelog

  • 1.0.0 - initial release: REST API discovery (wp-json / rest_route), posts/pages/custom types with pagination, Markdown + text conversion, taxonomies/authors/media export, incremental sync, sitemap/RSS/HTML fallback, pay-per-event charging.