Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To capture a WordPress website with an API, treat “capture” as collecting its structured content and metadata—not taking a rendered screenshot or making a complete backup. WordPress’s site-specific REST API returns JSON for resources such as posts, pages, taxonomies and media. Discover the site’s API index, request the resource you need, paginate large collections, and authenticate only when permissions require it.

If you actually need a visual image of a page, or a restorable copy of the whole site, use a screenshot or backup workflow instead; the REST API documentation does not establish either as a complete solution.

What “capture” means in WordPress

The official WordPress REST API Handbook describes an interface for applications to interact with a WordPress site by sending and receiving JSON objects. A capture script can therefore collect titles, content, authors, dates, slugs, featured-media IDs, page hierarchies and other exposed fields for later processing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Structured capture: JSON records from posts, pages, media, taxonomies and registered custom resources.
  • Visual capture: a rendered PNG, JPEG, WebP or PDF of what a browser displays. The WordPress REST API is not documented as a screenshot service.
  • Backup: a restorable copy of files and the database. API responses alone are not a complete WordPress backup.

The remainder of this guide covers structured API capture. It uses the target site’s own API root because self-hosted WordPress has no universal hostname or route configuration.

Discover the site’s API and available routes

Most WordPress sites expose an API index at /wp-json/. Replace the example host with the site you are authorized to query:

curl -i https://example.com/wp-json/

The JSON index advertises namespaces and routes available on that installation. Follow the links or inspect the route list rather than assuming every plugin, custom post type or field exists. The REST API Reference documents built-in resources, while the site index reflects what this particular site exposes.

When /wp-json/ does not work

  • A security plugin, host rule or reverse proxy may block REST requests.
  • Permalinks or rewrite rules may be misconfigured; a site can sometimes use an alternative API path that the installation documents.
  • A response can be HTML instead of JSON if the URL redirects to a login page, maintenance page or error document. Check the status code and Content-Type.

Do not infer that a route is readable merely because it appears in the index. Authentication and capability checks still apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Capture public posts and pages

Published public content is generally readable without credentials. Posts use /wp-json/wp/v2/posts; pages use /wp-json/wp/v2/pages. The endpoint references document fields, filters and pagination for each resource: posts and pages.

Fetch a small sample

curl -sS "https://example.com/wp-json/wp/v2/posts?per_page=10" 
  -H "Accept: application/json"

curl -sS "https://example.com/wp-json/wp/v2/pages?per_page=10" 
  -H "Accept: application/json"

Each response is a JSON array. A record commonly includes an id, date, slug, link, title, content, excerpt, author, featured_media and status-related fields. The content.rendered value is rendered HTML; do not assume it is safe to insert into another system without applying that system’s sanitization policy.

Paginate instead of assuming one response contains everything

Collections are paginated. Use page and per_page (within the site’s accepted limit), then continue until the server returns an empty page or until the response headers indicate that you have reached the final page. WordPress commonly returns X-WP-Total and X-WP-TotalPages; handle their absence gracefully because proxies or custom implementations can alter headers.

curl -sS "https://example.com/wp-json/wp/v2/pages?page=2&per_page=50"

Useful page filters include search, date constraints and ordering. Confirm the exact arguments in the endpoint’s reference for the resource and WordPress version you are calling; do not copy a posts-only argument to a custom route without checking.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python collection example

import requests

base = "https://example.com/wp-json/wp/v2/posts"
page = 1
records = []

while True:
    response = requests.get(
        base,
        params={"page": page, "per_page": 50, "orderby": "date", "order": "asc"},
        headers={"Accept": "application/json"},
        timeout=30,
    )
    response.raise_for_status()
    batch = response.json()
    if not batch:
        break
    records.extend(batch)
    total_pages = int(response.headers.get("X-WP-TotalPages", page))
    if page >= total_pages:
        break
    page += 1

print(f"Captured {len(records)} posts")

Node.js request example

const endpoint = new URL('https://example.com/wp-json/wp/v2/pages');
endpoint.search = new URLSearchParams({ page: '1', per_page: '20' });

const response = await fetch(endpoint, {
  headers: { Accept: 'application/json' }
});
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
const pages = await response.json();
console.log(pages.map(p => ({ id: p.id, slug: p.slug, title: p.title.rendered })));

Authenticate for private data and writes

Anonymous requests normally see public, published material. Drafts, private or password-protected content, unexposed metadata and write operations require the site’s permission model. An endpoint’s existence does not grant access.

Self-hosted WordPress: Application Passwords

For supported self-hosted installations, WordPress documents Application Passwords as per-application credentials that can be revoked independently. Create one in the user profile, give it a descriptive name, and store it in a secret manager or environment variable. Do not put your normal interactive login password in a script.

export WP_URL="https://example.com"
export WP_USER="api-user"
export WP_APP_PASSWORD="paste-the-generated-application-password"

curl -sS -u "$WP_USER:$WP_APP_PASSWORD" 
  -H "Accept: application/json" 
  "$WP_URL/wp-json/wp/v2/posts?context=edit&per_page=10"

Use HTTPS, restrict the account’s role and revoke the application credential when it is no longer needed. A 401 or 403 can mean invalid credentials, a disabled authentication method, or insufficient capability.

Creating a post

The posts reference documents the POST /wp/v2/posts operation. Test against a staging site or use a non-public status first:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -sS -X POST "$WP_URL/wp-json/wp/v2/posts" 
  -u "$WP_USER:$WP_APP_PASSWORD" 
  -H "Content-Type: application/json" 
  -d '{"title":"API draft","content":"<p>Created through the REST API.</p>","status":"draft"}'

Validate the returned JSON and retain the new ID. Sending HTML does not bypass WordPress capability checks or content filtering.

WordPress.com and Jetpack-connected sites

WordPress.com uses its own documented URL patterns and access-token flow. Its Getting Started documentation covers WordPress.com and Jetpack-connected self-hosted sites. Do not substitute a WordPress.com token URL for a self-hosted site’s /wp-json/ endpoint, or present one authentication scheme as universal.

Capturing media safely

Media has a dedicated route, documented in the WordPress media reference. You can list accessible attachments and use fields such as source URLs and dimensions:

curl -sS "https://example.com/wp-json/wp/v2/media?media_type=image&per_page=20"

Upload behavior depends on the endpoint, host configuration, permissions and enabled plugins. The WordPress.com service documents a separate media upload endpoint. Verify the exact request body, multipart format and file limits against the API you are using before automating uploads; the existence of a media route is not a guarantee that one upload recipe works on every host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Custom post types, taxonomies and metadata

Built-in posts and pages are only part of a site’s data. A custom post type must be registered for REST exposure (commonly with show_in_rest enabled), and its route and namespace may differ. Custom fields can be omitted unless the plugin or theme explicitly exposes them. Taxonomies likewise have their own routes and permission rules.

Inspect the API index and a representative response before designing your schema. Record the source URL, retrieval time, resource type and ID so later runs can detect changes without duplicating records.

A reliable capture workflow

  1. Confirm authorization and purpose. Capture only data you are allowed to process, and decide whether you need public content, privileged content, or writes.
  2. Discover routes. Request /wp-json/, inspect namespaces and verify the endpoint for posts, pages, media or a custom type.
  3. Probe one record. Check status, content type and field shape before starting a bulk run.
  4. Paginate deterministically. Set an explicit order, retain IDs and stop at the documented final page.
  5. Handle retries. Back off on 429 and transient 5xx responses; do not blindly repeat a write.
  6. Store provenance. Keep the site URL, endpoint, query parameters, retrieval timestamp and response status alongside captured data.
  7. Protect secrets. Use environment variables or a secret manager, HTTPS and revocable application credentials.

Performance, limits and cost considerations

The REST API does not promise a universal page size, rate limit or response-time figure. Larger per_page values reduce request count but increase response size and server work; start conservatively and adjust while watching for 429, timeout or memory errors. Request only needed fields where the endpoint supports an explicit field-selection parameter, and cache unchanged records using IDs, dates or your own checksum.

API requests may trigger database queries, plugin hooks and authentication checks on the WordPress host. Schedule large captures outside busy periods when you control the site, and coordinate with the owner when you do not. Your HTTP client, hosting provider and any WordPress.com plan can impose separate limits; check their current terms rather than assuming the REST API is unlimited.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting common failures

Symptom Likely cause Fix
404 on /wp-json/ Rewrite, proxy or security configuration Check permalinks, proxy rules and the site’s documented API path; inspect redirects.
200 response containing HTML Login, maintenance or error page Check Content-Type, final URL and response body before parsing JSON.
401 Unauthorized Missing, malformed or revoked credentials Regenerate an Application Password, use HTTPS and verify the username format.
403 Forbidden Insufficient capability or endpoint policy Use an account with the required capability or ask the site administrator to expose the resource.
400 on a page beyond the end Requested page exceeds the collection Read pagination headers and stop at the final page instead of treating it as a fatal outage.
Missing custom fields Metadata is not registered for REST Enable explicit REST exposure in the responsible plugin/theme or use an approved alternate export.
429 or repeated 5xx Rate limiting or temporary server failure Reduce concurrency, add exponential backoff and resume from the last stored ID.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If “capture” means a rendered screenshot rather than JSON content, ScreenshotNeo is a separate website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and whether it was billed. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for the 63 options, including full-page lazy-image loading, CSS-selector element capture, device presets, retina scale, PDF paper and page settings, custom CSS/JavaScript, clicks, waits, blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and OpenAPI details. Existing parameter names used by other screenshot APIs also work for easier migration.

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo.

What the REST API cannot tell you

A successful JSON capture does not prove that every visual element, private revision, plugin setting, uploaded original or database table has been collected. For a complete migration or disaster-recovery backup, follow a WordPress backup/export procedure that covers the database and files. For a pixel-level record, use a screenshot service or browser automation. Keep those outputs separate from your REST dataset so users understand exactly what was captured.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Can I capture a WordPress site without logging in?

Usually for public, published resources. Private, draft, password-protected, write and non-exposed metadata operations require the site’s authentication and capability checks.

Is the WordPress REST API the same on WordPress.com and self-hosted WordPress?

No. Self-hosted sites expose a site-specific REST root, commonly /wp-json/, while WordPress.com documents separate URL patterns and access tokens, including a service for Jetpack-connected sites.

Does an API capture include every custom field?

Only fields explicitly exposed by the responsible post type, plugin or theme and permitted for the requesting user are returned.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.