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

To put an html2canvas capture in the WordPress Media Library, render the element to a canvas, export the canvas as an image Blob, then send that Blob as a file to WordPress’s POST /wp/v2/media REST endpoint. A successful upload returns an attachment record; rendering the canvas alone does not create a Media Library item.

The browser-to-REST method below is suited to a capture button on a logged-in WordPress page. If the image is already a server-side file, use WordPress’s PHP media functions instead.

What the process does—and does not do

html2canvas returns a canvas asynchronously. It reconstructs an image from the DOM and CSS properties it understands; it does not take a native screenshot of the browser’s rendered pixels. The canvas is still only in browser memory. To create a WordPress attachment, export its pixels to a Blob and upload the Blob to the Media REST API or pass a file to WordPress server-side upload functions.

This distinction helps with debugging: a page can render successfully but fail during export or upload. Treat each stage as a separate operation and report success only after WordPress returns the attachment information.

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

Browser implementation: capture and upload

Prerequisites

  • Load the html2canvas library on the page and pass an element, such as document.querySelector('#capture-area').
  • Run the request in the context of a logged-in WordPress user who has permission to upload media.
  • Provide the WordPress REST root and a REST nonce generated through WordPress’s supported script setup. The nonce is sent as X-WP-Nonce.
  • Ensure images and other external assets can be read by the browser’s canvas security model. useCORS cannot override a remote host’s CORS policy.

WordPress documents cookie-and-nonce authentication for logged-in REST requests and Application Passwords over HTTPS for external applications. Do not put an Application Password in browser JavaScript: public page code is visible to visitors. See WordPress REST API authentication.

Complete capture function

This function expects html2canvas to be available, a DOM element to capture, the REST root (for example, the value WordPress exposes for rest_url()), and a nonce for the current logged-in user.

async function captureAndUpload(element, restRoot, nonce) {
  const canvas = await html2canvas(element, {
    backgroundColor: "#ffffff",
    useCORS: true,
  });

  const blob = await new Promise((resolve, reject) => {
    canvas.toBlob((result) => {
      if (result) resolve(result);
      else reject(new Error("Canvas could not be exported as an image."));
    }, "image/png");
  });

  const form = new FormData();
  form.append("file", blob, "capture.png");

  const response = await fetch(`${restRoot}wp/v2/media`, {
    method: "POST",
    headers: { "X-WP-Nonce": nonce },
    body: form,
    credentials: "same-origin",
  });

  const result = await response.json();
  if (!response.ok) {
    throw new Error(result.message || "WordPress media upload failed.");
  }
  return result; // Attachment object, including its ID and media URL.
}

Call it from a page interaction and handle failures visibly:

const button = document.querySelector("#save-capture");
const target = document.querySelector("#capture-area");

button.addEventListener("click", async () => {
  button.disabled = true;
  try {
    const attachment = await captureAndUpload(
      target,
      window.wpApiSettings.root,
      window.wpApiSettings.nonce
    );
    console.log("Uploaded attachment", attachment.id, attachment.source_url);
  } catch (error) {
    console.error("Capture or upload failed:", error);
    alert(error.message);
  } finally {
    button.disabled = false;
  }
});

The window.wpApiSettings.root and window.wpApiSettings.nonce names in this example are illustrative: expose the REST root and nonce using your site’s supported WordPress script-enqueue/localization approach, and use the names your script actually receives. Do not assume those globals exist by default.

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

Why the request is multipart

The endpoint receives the image bytes in a multipart form field named file. The filename passed to form.append() becomes the uploaded filename. Do not manually set the multipart Content-Type header: the browser must add the boundary that separates the form parts. The REST endpoint and attachment controller are documented in WordPress’s REST attachments controller reference.

On success, the response is an attachment object. Store or use its ID and media URL as appropriate; do not treat a resolved canvas Promise or a completed fetch() call as proof of success without checking response.ok.

Choose the image output deliberately

The example exports PNG with a white background. html2canvas supports a transparent background by setting backgroundColor to null, and its options include controls such as scale, width and height. Raising scale can improve detail but also increases canvas dimensions and memory use. Set dimensions and background for the actual content rather than assuming the default will fit every use case. See the html2canvas options reference.

When browser upload is not the right route

Route Use it when Input and authorization Trade-off
Browser REST upload A logged-in page offers a capture button and should upload directly. Image Blob sent to POST /wp/v2/media; REST nonce and user permission to upload. Little server-side code, but browser authentication, CORS and request formatting must be right.
media_handle_upload() A conventional WordPress form submits an uploaded file. WordPress receives a file in $_FILES; function returns an attachment ID or WP_Error. Fits ordinary form handling; the client must submit a file rather than only an in-memory canvas.
media_handle_sideload() Plugin code already has a local temporary file. Pass a $_FILES-style array, a post ID, and the temporary file. Useful for server-held files; code must handle errors and clean up temporary files.

PHP form upload

Use media_handle_upload() when WordPress receives an ordinary uploaded file through a POST form represented in $_FILES. It creates an attachment and returns its ID or a WP_Error; check which result you received before reporting success.

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

PHP sideload

Use media_handle_sideload() when plugin code has already written the image to a server-side temporary file. Supply the expected file-array data and post ID. Use post ID 0 for an unattached Media Library item. Check for WP_Error, and remove the temporary file after a failed sideload where appropriate.

These PHP functions do not upload a browser canvas by themselves. The browser must first transmit the file to your WordPress handler, or server code must create a temporary file from image data before sideloading it.

Cross-origin images and html2canvas limits

Canvas export can fail or omit an image when the captured page uses resources from another origin. Browsers restrict reading back a canvas containing cross-origin pixels unless the remote server allows it. html2canvas’s useCORS: true asks the browser to use CORS for eligible image requests; it does not bypass that restriction. The remote image host must return appropriate CORS headers. See the html2canvas FAQ.

If the asset host cannot be configured to permit CORS, use a controlled server-side proxy or exclude the asset. A proxy should be restricted to known, authorized destinations; an unrestricted proxy can be abused to fetch arbitrary URLs. html2canvas’s output is also limited by the DOM features and CSS properties it supports, so visually complex pages may not exactly match the browser view. The project explains this distinction in Getting Started and About html2canvas.

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

Troubleshooting common failures

Canvas export returns no Blob or throws

  • Check whether a cross-origin image tainted the canvas.
  • Confirm the image server permits CORS; setting useCORS: true alone is not permission.
  • Test without the external resource, or move it through a controlled proxy.
  • Handle the null callback result from toBlob() as a failure, as the example does.

WordPress returns unauthorized or forbidden

  • Confirm the browser is logged in to the same WordPress site and the request uses credentials: "same-origin".
  • Check that the nonce is current and sent under the exact X-WP-Nonce header.
  • Verify the REST root points to the intended site and the current user is allowed to upload media.
  • For an external server client, use a suitable HTTPS authentication method; never expose Application Passwords in browser code.

WordPress rejects the image or the server fails to process it

Inspect the response status and body, then check the submitted filename and image type, WordPress validation, and the host’s upload limits. Limits vary by installation and hosting configuration; there is no universal size limit established here. If you switch to PHP handling, check the returned ID or WP_Error instead of assuming the attachment was created.

The uploaded image looks wrong, blank or clipped

  • Remember that html2canvas reconstructs the page from DOM and supported CSS; it is not a pixel-perfect native browser screenshot.
  • Set an explicit background when transparency is not intended.
  • Check the target element’s dimensions and adjust width, height or scale as needed.
  • For content outside the visible viewport, inspect html2canvas’s window-size and rendering options and confirm the element dimensions before exporting.

The request appears to complete but no attachment is saved

Check response.ok before using the response, parse the JSON error body when available, and verify that a successful response contains an attachment record. A network response is not necessarily a successful upload.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and cost considerations

Large captures require more browser memory because the page must be rendered into a canvas and encoded into an image before upload. Use an appropriate capture region and output scale, avoid unnecessarily large dimensions, and consider server-side processing if the capture or upload must run unattended. Network timeouts, authentication expiry, server validation and hosting limits are separate failure points; design the interface to show a clear failure and allow a deliberate retry rather than silently claiming success.

The browser flow has no separate service price in this implementation, but it consumes client and WordPress server resources and depends on the site’s upload configuration. A screenshot API is a different approach: it renders a URL remotely rather than capturing an element already rendered in the user’s browser. Consider that distinction if your underlying need is a page screenshot rather than saving a specific component from the current WordPress page.

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.

Or skip the browser setup

If you need a screenshot of a URL rather than an existing DOM element, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request can return an image or PDF; it is not a replacement for html2canvas when you specifically need to capture an in-memory element in the visitor’s current page. Its documented features include accepting cookie and consent banners before capture and removing more than 60 known consent platforms, newsletter popups and chat widgets, with each step switchable. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and responses identify the page verdict and billing status in headers. AI agents can use its MCP tools, including take_screenshot, get_page_info and capture_pdf.

Example cURL request (replace the URL with the page to capture):

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 API documentation for authentication and request options. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month with no card.

FAQ

Does html2canvas create a Media Library attachment?

No. It creates a browser canvas. Export that canvas to an image Blob and upload it to WordPress, or pass a server-side file through WordPress’s media functions.

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.

Can I use this method while logged out?

The nonce example is for an authenticated, same-site logged-in user. A public upload form needs a server-side design that safely validates and authorizes submissions; do not expose privileged credentials in page JavaScript.

Can I upload a PDF from this canvas code?

The code exports PNG. PDF generation is a separate workflow and is not performed by the shown html2canvas-to-media request.

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.