ScreenshotNeo

BlogHTML to image & PDF

How to Embed a PDF in HTML: Example Code

Embed PDFs with accessible iframe or object markup, responsive sizing, fallback links, CSP fixes, troubleshooting, and production guidance.

By the ScreenshotNeo team1 October 20267 min read

For a straightforward PDF preview, point an <iframe> at the PDF and provide a normal link outside it. The link remains useful when the embedded viewer is unavailable, blocked by policy, or difficult to use on a particular device.

<iframe
  src="/files/guide.pdf"
  title="PDF: Guide"
  width="100%"
  height="600"
></iframe>

<p>
  <a href="/files/guide.pdf">Open or download the PDF</a>
</p>

Use a URL that your visitors can access, give the frame enough space for reading, and make the title describe the document. MDN recommends a descriptive iframe title for screen-reader users and a separate link because an iframe has no child fallback when its content cannot be displayed. See MDN’s iframe reference.

1. Embed a PDF with an iframe

An iframe creates a browsing context for the PDF viewer supplied by the browser. It is the best default when you need a native preview with loading and referrer controls.

<section aria-labelledby="guide-heading">
  <h2 id="guide-heading">Product guide</h2>

  <iframe
    src="/files/guide.pdf"
    title="Product guide PDF"
    width="100%"
    height="720"
    loading="lazy"
    referrerpolicy="no-referrer"
  ></iframe>

  <p>
    <a href="/files/guide.pdf">Open or download the product guide (PDF)</a>
  </p>
</section>

Responsive sizing

The HTML width and height attributes provide an initial size. CSS makes the frame fill its container while retaining a usable reading area.

.pdf-frame {
  display: block;
  width: 100%;
  min-height: 36rem;
  border: 0;
}

@media (max-width:  fortyrem) {
  .pdf-frame {
    min-height: 28rem;
  }
}

Correct the media query value to a valid CSS length such as 40rem:

@media (max-width: 40rem) {
  .pdf-frame {
    min-height: 28rem;
  }
}

Apply the class to the iframe:

<iframe
  class="pdf-frame"
  src="/files/guide.pdf"
  title="Product guide PDF"
></iframe>

Useful iframe attributes

Attribute Use
src Absolute or relative URL of the PDF.
title Describes the document to assistive technology; use a specific name.
width, height Initial dimensions in CSS pixels; CSS can make the frame responsive.
loading="lazy" Defers loading until the frame is near the viewport.
referrerpolicy Controls the referrer sent when requesting the PDF.

Keep the download link outside the iframe. The embedded viewer may load while still failing to render a particular file, and iframe contents cannot contain your fallback markup.

2. Use object when you need inline fallback content

<object> identifies the resource with data and type="application/pdf". Its child HTML can be shown when the PDF cannot be rendered.

<object
  data="/files/guide.pdf"
  type="application/pdf"
  width="100%"
  height="600"
>
  <p>
    PDF preview unavailable.
    <a href="/files/guide.pdf">Open or download the PDF</a>.
  </p>
</object>

<p>
  <a href="/files/guide.pdf">Open or download the PDF</a>
</p>

The outside link is still useful because fallback content does not cover every case in which a viewer opens but does not display the document. See MDN’s object reference.

3. What about embed?

<embed
  src="/files/guide.pdf"
  type="application/pdf"
  title="Product guide PDF"
  width="100%"
  height="600"
>

<embed> can display browser-handled content such as PDFs, but it is a void element: it cannot contain fallback markup. MDN notes that it offers no advantage over iframe for PDF previews. If you use it, include a separate link and a descriptive title. Its width and height attributes are absolute CSS-pixel values. See MDN’s embed reference.

4. Make the embed accessible

  • Give the iframe or embed a document-specific title, such as Annual security report PDF.
  • Put a normal link before or after the preview so keyboard and assistive-technology users have a direct route.
  • Include the file type and, when useful, file size in the link text: Download pricing guide (PDF, 2.4 MB).
  • Do not rely on the PDF viewer as the only way to access essential information. Provide equivalent HTML content when the document contains critical instructions or data.
  • Use a heading that explains what the embedded document is, and group the frame and link in a labelled section.

5. Security, CSP and cross-origin delivery

Content Security Policy

Your Content Security Policy can allow one element while blocking another:

  • iframe sources are controlled by frame-src.
  • object and embed sources are controlled by object-src.

If your policy sets object-src 'none', a native iframe preview can still be the viable option when frame-src permits the PDF origin. Inspect the browser console for a CSP violation and add only the specific origin you need.

Do not add sandbox casually

Browser PDF renderers already sandbox executable PDF content. Adding an iframe sandbox attribute solely to sandbox the built-in viewer can stop that viewer from working and is not a portable control for native PDF preview behavior. Use your site’s security policy and document-serving controls instead. See MDN’s iframe security guidance.

Cross-origin URLs

An iframe can navigate to a PDF hosted on another origin when that origin permits framing. A custom JavaScript viewer that fetches PDF bytes is subject to CORS rules. Mozilla’s PDF.js FAQ documents URL-loading CORS constraints and notes that supported PDF features depend partly on browser capabilities.

Serve the file correctly

Configure the server to return the PDF with Content-Type: application/pdf. Keep the PDF URL stable, require authentication only when the embedding page and viewer can send the required credentials, and make sure access-control rules allow the intended audience.

6. Optional query parameters and download behavior

Some native viewers accept fragment parameters such as a starting page, but support is viewer-dependent. Do not make navigation fragments a requirement for accessing the document. The direct link should always open the original PDF.

<iframe
  src="/files/guide.pdf#page=3"
  title="Product guide PDF, starting on page 3"
  width="100%"
  height="600"
></iframe>

If you need a forced download rather than an inline preview, use a separate download endpoint or an appropriate server response such as Content-Disposition: attachment. Keep the preview URL and download URL clear in the interface.

7. Troubleshooting common failures

Symptom Likely cause Fix
Blank frame Wrong URL, authentication failure, or the server returned HTML instead of a PDF. Open the URL directly, inspect the network response, and verify status and Content-Type: application/pdf.
CSP console error frame-src or object-src blocks the PDF origin. Allow the specific origin in the directive used by your chosen element.
Fallback text never appears The browser opened a viewer, even though that viewer could not render the file. Keep a link outside <object> and test the direct URL separately.
Viewer fails after adding sandbox The sandbox restrictions interfere with the native PDF viewer. Remove the sandbox attribute unless you have a tested, viewer-compatible design.
Cross-origin custom viewer error PDF.js or another script cannot fetch the file because of CORS. Configure CORS on the PDF origin or proxy the file through an authorized server endpoint.
Mobile frame is too short Fixed height does not match the small viewport. Use a responsive CSS class with a smaller minimum height at narrow widths and retain the direct link.
Private PDF prompts unexpectedly The embedded request lacks the cookie or authorization required by the file server. Use an access-controlled endpoint designed for the embedding context; never expose a secret token in client-side HTML.

8. Performance and reliability checklist

  • Use loading="lazy" for PDFs below the fold.
  • Set a reserved height so the page does not jump when the frame loads.
  • Keep the PDF reasonably sized and optimize it during your publishing pipeline.
  • Use a cacheable, versioned URL for documents that change infrequently.
  • Keep the direct link visible if the viewer times out or is unavailable.
  • Test with the same authentication, CSP and hosting origin used in production.
  • Check keyboard focus order and screen-reader output for the heading, frame title and link.

9. Generate a PDF or image without maintaining browser embed code

If your actual goal is to publish a reliable visual copy of a page, ScreenshotNeo can capture a URL as an image or PDF through one GET request. It handles the browser setup and exposes PDF options such as paper size, margins, landscape mode and page ranges. Read the ScreenshotNeo API documentation.

Or skip the browser setup

Use the ScreenshotNeo endpoint with your page URL:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com/report.html \
  -o report.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com/report.html"},
    timeout=90,
)
r.raise_for_status()
open("report.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com/report.html'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('report.webp', data);

ScreenshotNeo removes cookie banners, newsletter popups and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor and other MCP clients use take_screenshot, get_page_info and capture_pdf. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

10. FAQ

Should I use iframe or object?

Start with iframe for a native preview and its loading controls. Choose object when inline fallback markup is particularly useful, while keeping an outside link in either case.

Can I embed a PDF from another domain?

Yes, when the remote server permits framing and the document is accessible to the viewer. A script-based viewer also needs CORS permission to fetch the PDF.

A viewer can open without rendering the file, and iframe has no child fallback. A normal link gives users a separate, dependable access path.

Do I need PDF.js?

No. Use the browser’s native viewer for a simple preview. Consider a custom viewer only when you need a controlled interface or behavior beyond native support, and check current PDF.js documentation for deployment details.