Running Airgapped / Offline
By default, the EmbedPDF Snippet is optimized for a zero-config developer experience and pulls a handful of assets from public CDNs. For network-restricted environments, such as intranets or airgapped infrastructure, you can redirect or disable those external requests.
This guide walks through every CDN default in the snippet and shows how to redirect or disable each one.
The Defaults to Know
| Asset | Default source | Triggered by |
|---|---|---|
pdfium.wasm | cdn.jsdelivr.net/npm/@embedpdf/pdfium | Viewer init |
| PDFium font fallback (fonts for missing glyphs) | cdn.jsdelivr.net/npm/@embedpdf/fonts-* | Rendering text the PDF’s embedded fonts can’t cover |
| Snippet UI + signature webfonts | fonts.googleapis.com / fonts.gstatic.com | Viewer init (UI font) and opening the Create Signature modal (signature fonts) |
| Default stamp library | cdn.jsdelivr.net/npm/@embedpdf/default-stamps | Stamp plugin init (Rubber Stamp panel) |
Each of them is independently configurable via EmbedPDF.init.
1. Self-host the PDFium WebAssembly binary
Copy the wasm file out of @embedpdf/pdfium at build time and serve it from your own origin, then point wasmUrl at it.
cp node_modules/@embedpdf/pdfium/dist/pdfium.wasm public/pdfium.wasmEmbedPDF.init({
target: document.getElementById('pdf-viewer'),
src: '/document.pdf',
wasmUrl: '/pdfium.wasm',
});The wasm file is a few MB in size. Serving it with long-lived cache headers (Cache-Control: public, max-age=31536000, immutable) alongside a versioned filename works well.
2. Replace the PDFium font fallback CDN
When a PDF references a font that isn’t embedded (common with East Asian languages, Hebrew, Arabic, etc.), PDFium needs a fallback font to render correctly. The snippet’s default downloads those fonts from jsDelivr. You have three options:
Option A — Disable fallback entirely
Set fontFallback to null. Missing glyphs will render as “tofu” boxes but no external request is made.
EmbedPDF.init({
// ...
fontFallback: null,
});Option B — Self-host the fonts
Install the font packages you need and provide a custom FontFallbackConfig pointing at URLs you serve yourself. The @embedpdf/fonts-* packages ship the raw font files and ready-made font definitions you can reuse.
import { FontCharset } from '@embedpdf/models';
EmbedPDF.init({
// ...
fontFallback: {
fonts: {
[FontCharset.SHIFTJIS]: '/fonts/NotoSansJP-Regular.otf',
[FontCharset.GB2312]: '/fonts/NotoSansSC-Regular.otf',
// ...add any charsets your documents need
},
},
});See the individual font package READMEs (@embedpdf/fonts-jp, @embedpdf/fonts-sc, @embedpdf/fonts-tc, @embedpdf/fonts-kr, @embedpdf/fonts-arabic, @embedpdf/fonts-hebrew, @embedpdf/fonts-latin) for the exact file names and recommended weights.
3. Configure or opt out of webfonts
The snippet uses two families of external webfonts, both configurable through the top-level fonts key:
fonts.ui— the UI chrome font (Open Sans by default). Loaded once at viewer init.fonts.signature— the cursive fonts in the “Type” tab of the Create Signature modal (Caveat, Dancing Script, Great Vibes, Pacifico by default). Loaded lazily when the modal opens.
Both stylesheets are registered at document scope as deduped <link rel="stylesheet"> elements in document.head. That is intentional: browser support for @font-face inside shadow DOM is inconsistent, and the typed signature renderer draws text to <canvas>, which resolves fonts from the document-level font registry.
The snippet first reuses an existing matching stylesheet URL if your host page already loaded it. It can also skip injecting when document.fonts already exposes the requested family. Managed links are marked with data-embedpdf-fonts="ui" or data-embedpdf-fonts="signature" for auditing.
The high-level resolution rules are:
undefined(omitted) — load the Google Fonts default.null— skip the managed stylesheet. Text falls back through the configured CSSfont-familystack to local/system fonts.- custom config — use your own stylesheet URL, font family, and/or signature font list.
UI font
fonts.ui uses the same object shape as fonts.signature: stylesheetUrl controls loading, and UI adds a family field for the CSS font stack.
// Disable the UI font entirely. Viewer chrome uses the system font stack.
EmbedPDF.init({
// ...
fonts: { ui: null },
});
// Or point to your own stylesheet.
EmbedPDF.init({
// ...
fonts: {
ui: { stylesheetUrl: '/fonts/open-sans.css' },
},
});
// Use a different UI font. This is useful for branding and for testing on
// machines that already have Open Sans installed locally.
EmbedPDF.init({
// ...
fonts: {
ui: {
family: "'Lora', serif",
stylesheetUrl: 'https://fonts.googleapis.com/css2?family=Lora:wght@400;600&display=swap',
},
},
});
// Use a font that your host page already provides. No extra <link> is added.
EmbedPDF.init({
// ...
fonts: {
ui: {
family: "'Inter', system-ui, sans-serif",
stylesheetUrl: null,
},
},
});Signature “Type” tab fonts
// Fully disable the signature webfonts.
EmbedPDF.init({
// ...
fonts: { signature: null },
});
// Self-host the stylesheet (same four families).
EmbedPDF.init({
// ...
fonts: {
signature: { stylesheetUrl: '/fonts/signature-fonts.css' },
},
});
// Use a different font list. The fonts must already be available —
// either provided by the given `stylesheetUrl`, or loaded elsewhere
// in your app. Omit `stylesheetUrl` to skip the managed <link> entirely.
EmbedPDF.init({
// ...
fonts: {
signature: {
fonts: [
{ name: 'Brand Script', family: "'Brand Script', cursive" },
{ name: 'Mono', family: "'JetBrains Mono', monospace" },
],
},
},
});When signature fonts are fully disabled, the Create Signature modal hides the “Type” tab. The “Draw” and “Upload” tabs remain available.
When a signature stylesheet is loaded, the snippet also calls document.fonts.load(...) for each configured family before rendering typed signatures. This prevents the hidden canvas from drawing with the generic cursive fallback while the real font file is still loading.
The four defaults (Caveat, Dancing Script, Great Vibes, Pacifico) are all licensed under the SIL Open Font License, so you can freely redistribute them alongside a self-hosted build.
4. Disable or self-host the stamp library
The Rubber Stamp panel ships with a default stamp library that the stamp plugin loads at init from a locale-aware manifest on jsDelivr (cdn.jsdelivr.net/npm/@embedpdf/default-stamps/{locale}/manifest.json). The plugin fetches that manifest and the PDF it references, so it makes external requests on startup. Configure it through the top-level stamp key.
Option A — Disable the default stamps
Pass an empty manifests array. No external request is made. The Rubber Stamp panel stays functional for user-created stamps via the local default library.
EmbedPDF.init({
// ...
stamp: { manifests: [] },
});Option B — Self-host the stamp manifest
Serve the manifest (and the PDF it references) from your own origin and point manifests at it. The manifest’s pdf path is resolved relative to the manifest URL unless it is absolute.
EmbedPDF.init({
// ...
stamp: {
manifests: [{ url: '/stamps/manifest.json' }],
},
});The empty in-memory “Custom Stamps” library is created locally and never hits the network. If you don’t want the Rubber Stamp feature at all, you can also pass stamp: { manifests: [], defaultLibrary: false }, and hide the toolbar button entirely by disabling the insert-rubber-stamp category (see Customizing the UI).
Complete airgapped example
Putting it all together:
import EmbedPDF from '@embedpdf/snippet';
import { FontCharset } from '@embedpdf/models';
EmbedPDF.init({
target: document.getElementById('pdf-viewer'),
src: '/document.pdf',
// 1. Self-hosted wasm
wasmUrl: '/assets/pdfium.wasm',
// 2. Self-hosted font fallback (or set to null to disable)
fontFallback: {
fonts: {
[FontCharset.SHIFTJIS]: '/fonts/NotoSansJP-Regular.otf',
[FontCharset.GB2312]: '/fonts/NotoSansSC-Regular.otf',
},
},
// 3. No external webfonts for UI or signature modal.
fonts: {
ui: null,
signature: null,
},
// 4. No default stamp library fetched from the CDN.
stamp: { manifests: [] },
});With the configuration above the snippet makes no external network requests beyond fetching your PDF document itself.
Need Help?
Join our community for support, discussions, and to contribute to EmbedPDF's development.