ScreenshotNeo

BlogHow-to

How to Use the Adobe PDF Embed API: Demo and Setup

Embed a PDF with Adobe PDF Embed API: get a client ID, run working code, choose modes, handle mobile limits, and fix common errors.

By the ScreenshotNeo team1 October 20265 min read

How to Use the Adobe PDF Embed API: Demo and Setup

Short answer: Register your site for an Adobe client ID, load the viewer SDK, add a container, wait for adobe_dc_view_sdk.ready, create AdobeDC.View, then call previewFile with a PDF URL or file promise and a file name.

Adobe’s quick start requires no special environment setup. The client ID is checked against the domain serving the page, so a domain mismatch prevents preview. See the Adobe PDF Embed API documentation.

Prerequisites

  1. Register the website domain and copy its client ID.
  2. Provide a browser-readable PDF URL, or code that returns an ArrayBuffer.
  3. Choose a file name; Adobe requires metaData.fileName.

Adobe’s online demo can configure the viewer and generate starter code. Its ready-to-run samples help confirm that a PDF renders before you integrate it.

Minimal working embed

Save this as index.html, replace the placeholders, and serve it from the registered domain.

The minimum integration loads the SDK, waits for ready, creates a viewer, and previews the file.
The minimum integration loads the SDK, waits for ready, creates a viewer, and previews the file.
<!doctype html>
<html lang='en'>
<head>
  <meta charset='utf-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <title>PDF viewer</title>
  <style>#adobe-dc-view { width: 100%; height: 720px; }</style>
</head>
<body>
  <div id='adobe-dc-view'></div>
  <script src='https://acrobatservices.adobe.com/view-sdk/viewer.js'></script>
  <script>
    document.addEventListener('adobe_dc_view_sdk.ready', function () {
      const view = new AdobeDC.View({clientId: 'YOUR_CLIENT_ID', divId: 'adobe-dc-view'});
      view.previewFile({
        content: { location: { url: 'https://example.com/path/file.pdf' } },
        metaData: { fileName: 'file.pdf' }
      }, { embedMode: 'SIZED_CONTAINER' });
    });
  </script>
</body>
</html>

Keep the listener, SDK script, container, AdobeDC.View, and previewFile together. The PDF URL must be reachable by the browser.

Choose an embed mode

Mode Layout Best fit
FULL_WINDOW Fills the viewing area The PDF is the primary screen.
SIZED_CONTAINER Bounded box Dashboards and predictable layouts; set width and height.
IN_LINE Pages flow with surrounding content Whitepapers, brochures, ebooks, and reading pages.
LIGHT_BOX Foreground overlay Open a document without leaving the page.

Change embedMode to match the layout. A sized container needs a non-zero CSS height; inline viewers need space for the document’s pages.

Embed mode determines how the PDF occupies the surrounding page.
Embed mode determines how the PDF occupies the surrounding page.

Controls and options

Adobe documents options for download, print, annotation, full screen, search, and forms. Form filling is enabled by default and can be disabled.

view.previewFile(fileConfig, {
  embedMode: 'SIZED_CONTAINER',
  showDownloadPDF: true,
  showPrintPDF: true,
  showAnnotationTools: true,
  showFullScreen: true,
  showSearch: true,
  enableFormFilling: false
});

Private PDFs and file promises

Pass a promise resolving to an ArrayBuffer when the document is private. If URL and promise are both supplied, Adobe uses the promise and ignores the URL.

const filePromise = fetch('/api/report.pdf').then(r => {
  if (!r.ok) throw new Error(`PDF request failed: ${r.status}`);
  return r.arrayBuffer();
});
view.previewFile({content: {promise: filePromise}, metaData: {fileName: 'report.pdf'}});

Keep authorization on your server; do not place long-lived secrets in a page URL.

Test the source with cURL, Python, and Node.js

These snippets validate the PDF response before you debug the viewer.

cURL

curl -I -L 'https://example.com/path/file.pdf'

Python

import requests
r = requests.get('https://example.com/path/file.pdf', timeout=30)
r.raise_for_status()
open('file.pdf', 'wb').write(r.content)
print(r.headers.get('content-type'))

Node.js

const fs = require('node:fs/promises');
const res = await fetch('https://example.com/path/file.pdf');
if (!res.ok) throw new Error(`PDF request failed: ${res.status}`);
await fs.writeFile('file.pdf', Buffer.from(await res.arrayBuffer()));

Domain, CORS, and browser support

  • Register the exact hostname used in production; staging and localhost may need their own registration.
  • Test through a web server, not only file://.
  • The browser must be permitted to request the PDF. Configure the PDF host for required cross-origin requests or proxy it through your origin.
  • Watch SDK, PDF, redirect, and CORS requests separately in DevTools.

Adobe lists latest versions of Edge, Chrome, and Firefox on Windows; Safari, Chrome, Edge, and Firefox on macOS; Chrome on Android; and Safari and Chrome on iOS. Check Adobe’s current matrix when browser support is contractual.

Mobile limitations

  • Annotation tools are not supported on phones in FULL_WINDOW; Adobe documents them for Android and iOS tablets.
  • Print is unsupported on mobile.
  • PDF download is unsupported on iOS and supported on Android.

Troubleshooting

Symptom Cause Fix
Blank viewer or invalid client ID ID is wrong or belongs to another domain. Copy it again and register the exact serving domain.
Ready event never fires SDK failed to load or listener ran too late. Check the SDK request, attach the listener before initialization, and review content-security rules.
401/403 or HTML instead of PDF Authentication, redirect, or permission failure. Use an authorized URL or fetch server-side and pass a promise.
Metadata error Missing file name. Set metaData.fileName, such as report.pdf.
Viewer has no height Container height is zero. Set CSS height on #adobe-dc-view.
Works locally, fails in production Production hostname is unregistered. Register and retest the deployed URL.
Mobile controls missing Documented mobile limitation or disabled option. Use a supported tablet flow or offer a separate action.

Performance and reliability checklist

  • Use a nearby, cacheable URL for public PDFs.
  • Fetch private files once and pass the resulting bytes.
  • Show loading and error states around the container.
  • Keep file names meaningful and stable.
  • Test every mode at desktop and phone widths.

Or skip the browser setup

For a clean image or PDF of a web page, ScreenshotNeo uses one request. It removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; X-Page-Verdict and X-Billed identify the result. Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf.

See the ScreenshotNeo API docs:

curl -G 'https://api.screenshotneo.com/v1/shot' -d access_key=YOUR_API_KEY --data-urlencode url=https://developer.adobe.com/document-services/docs/overview/pdf-embed-api/ -o shot.webp
import requests
r = requests.get('https://api.screenshotneo.com/v1/shot', params={'access_key': 'YOUR_API_KEY', 'url': 'https://developer.adobe.com/document-services/docs/overview/pdf-embed-api/'}, timeout=90)
open('shot.webp', 'wb').write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://developer.adobe.com/document-services/docs/overview/pdf-embed-api/' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Cost notes

Adobe describes the PDF Embed API as free to use. Your own costs can include PDF hosting, bandwidth, authentication, and browser infrastructure. ScreenshotNeo plans are Free (1,000 shots/month), Starter $5/3,000, Growth $15/15,000, Pro $39/60, Scale $99/250,000, and Business $249/1,000,000; yearly billing gives two months free and every feature is on every plan.

FAQ

Can a private server PDF be embedded?

Yes. Fetch it in your application and pass a promise resolving to an ArrayBuffer.

Do I need React or a bundler?

No. Plain HTML and JavaScript are enough.

Which mode suits a whitepaper?

Adobe describes IN_LINE for whitepapers, brochures, ebooks, and similar reading.

Why does staging reject my client ID?

The ID is validated against the registered domain. Register the staging hostname or use the registered domain.