Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
The documented route is direct: put your markup and styles in an HtmlOutput, then call getAs('application/pdf'). This produces a PDF blob, but Google does not publish a CSS-compatibility matrix for the conversion. Treat CSS preservation as something to verify with representative PDFs—not as a guaranteed browser match.
Use HtmlOutput and getAs() for the conversion
Apps Script’s HTML Service lets a project include HTML, CSS and client-side JavaScript in an HtmlOutput. The API reference documents getAs(contentType) as returning the object’s data as a blob converted to the requested type. For PDF output, request application/pdf, assign a filename, and save or attach the blob.
function createPdf() {
const html = `
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font-family: Arial, sans-serif;
margin: 24px;
color: #222;
}
h1 { color: #174ea6; }
.note {
border: 1px solid #aaa;
padding: 12px;
}
</style>
</head>
<body>
<h1>Report</h1>
<p class="note">Generated from Apps Script.</p>
</body>
</html>`;
const pdf = HtmlService.createHtmlOutput(html)
.getAs('application/pdf')
.setName('report.pdf');
DriveApp.createFile(pdf);
}
setName() gives the resulting blob a predictable filename before it is written to Drive, returned from another function, or attached to an email. The example demonstrates the API shape; it is not a promise that every CSS property shown, or any other property, will render identically to Chrome.
Keep the HTML self-contained and conservative
Prefer ordinary document flow
Start with normal block flow, explicit widths where they are genuinely needed, readable margins, simple borders and predictable typography. This makes differences in the PDF easier to diagnose than a layout that depends on several advanced browser behaviors.
#1 Best Overall
Inline or embed critical styles
A single HTML string with a <style> block keeps the document’s essential rules together. If you use separate files in an HTML Service interface, active external content in IFRAME mode must be loaded over HTTPS. That sandbox rule concerns how HTML Service loads active content; it is not a published guarantee about PDF conversion support.
Do not assume browser CSS support
HTML Service supports HTML, CSS and client-side JavaScript, while Google notes that some advanced HTML5 features are unavailable. That authoring statement does not establish that flexbox, grid, web fonts, print-specific rules or JavaScript-driven layout will survive conversion. Avoid designing around an unverified property until it appears correctly in your own generated PDF.
Build a repeatable fidelity check
- Create a fixture document. Include the real headings, tables, images, long paragraphs, colors, links and page-length content used by your application.
- Generate the PDF from the same code path used in production. Do not validate only a simplified screen preview.
- Inspect the PDF itself. Check font substitution, color, element dimensions, image loading, margins, page boundaries, overflow and behavior at page breaks.
- Test long and awkward content. Include a long table cell, a heading at the bottom of a page, an image with its natural dimensions, and an unusually long word or URL.
- Record acceptable differences. If a layout requirement is strict, keep a sample PDF as a regression artifact and compare new output after template changes.
This process is necessary because the official references document the conversion API but do not publish a CSS support table for HTML-to-PDF output.
Handling styles that commonly cause surprises
Page size and page breaks
Do not promise that @page, @media print, or a particular page-break-* rule will work in this conversion. If page boundaries matter, generate several representative documents and inspect where content actually breaks. For regulated or print-critical output, regard an unverified rule as a risk rather than a contract.
Flexbox and grid
These can be convenient in a browser, but the reviewed Google documentation does not guarantee their PDF behavior. A conservative fallback is ordinary flow with block elements, explicit widths, and simple tables where tabular alignment is required.
Fonts
Use a dependable fallback stack such as Arial, sans-serif for predictable results. If a particular typeface is essential, verify that the generated PDF contains the expected appearance; do not infer support merely because the browser preview uses that font.
Rank #2
Images and remote assets
Test every image at the size and location used in production. A browser preview that displays a remote asset is not proof that the conversion will fetch it in the same way. For critical documents, prefer assets you control and confirm that they appear in the resulting blob.
Free tools Windows power users keep installed
One-click scans. No signup required.
Client-side JavaScript
HTML Service can contain client-side JavaScript, but a PDF conversion workflow should not depend on asynchronous browser behavior unless your own tests prove it completes before conversion. Render essential text and styles in the initial markup whenever possible.
Saving, returning, and attaching the PDF blob
Save to Drive
DriveApp.createFile(pdf) stores the blob and returns a Drive file. In a larger application, use the returned file ID to move the file, set permissions, or persist a reference in your data store.
Return from a function
If another Apps Script function needs the result, return the blob rather than creating a Drive file immediately:
function buildReportPdf() {
const output = HtmlService.createHtmlOutputFromFile('report');
return output.getAs('application/pdf').setName('report.pdf');
}
An HTML file named report.html can contain the document and its embedded style block. Keep the conversion boundary explicit so changes to the template are easy to test.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteEmail as an attachment
function emailReport() {
const pdf = buildReportPdf();
GmailApp.sendEmail('[email protected]', 'Report', 'Attached is the PDF.', {
attachments: [pdf]
});
}
Use the same fixture-and-inspection process when changing an emailed report; attachment delivery does not change the renderer’s CSS behavior.
Rank #3
- hole punched
- high quality card stock
- 4 pages
- made in USA
- keyboard shortcuts
Why CSS appears to disappear
- The rule is unsupported or behaves differently. The conversion API has no published CSS compatibility matrix.
- The stylesheet was not available. External resources can fail to load, and HTML Service sandbox requirements apply to active external content.
- JavaScript had not finished. A browser preview may show a post-load state that the conversion does not reproduce.
- The layout only works at one viewport. Fixed dimensions, overflow and long text can move content or clip it in a PDF.
- A font was substituted. Different metrics change line wrapping and therefore page breaks.
Reduce the document to a small fixture, replace advanced rules with ordinary flow, and add features back one at a time. That isolates whether the problem is loading, timing, unsupported CSS, or content length.
Choose the right rendering route
| Route | Best fit | What to verify |
|---|---|---|
HtmlOutput.getAs('application/pdf') |
HTML templates already running in Apps Script | Actual CSS, fonts, images, JavaScript timing and page breaks in generated samples |
Document.getAs('application/pdf') |
Reports that can be assembled naturally as Google Docs | That the content model works as a Docs document; this is not HTML/CSS preservation |
| Hosted HTML-to-PDF renderer | Layouts whose required fidelity exceeds the built-in route | Supported CSS and JavaScript, page options, privacy terms, cost, reliability and data handling |
The Google Docs method is a separate content workflow. It should not be presented as exporting arbitrary HTML while preserving its original CSS.
Or skip the browser setup
If your goal is a clean capture of a rendered web page rather than an Apps Script-native conversion, ScreenshotNeo provides a website screenshot API and MCP server. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms, newsletter popups and chat widgets before capture, and reports whether a response was billed. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed.
Recommended Free Tools
For a direct request, see the ScreenshotNeo documentation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Equivalent 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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf for AI clients, plus full-page capture, CSS-selector element capture, device presets, custom CSS and JavaScript, waits, request blocking, cookies, headers, geolocation, resizing, caching, signed links, asynchronous jobs and bulk capture. Every plan includes every feature. The Free plan includes 1,000 shots each month with no card; paid plans start at $5 for 3,000 shots. Sign up free.
Troubleshooting checklist
The function throws before creating a file
Confirm that the HTML string is valid JavaScript, the requested content type is exactly application/pdf, and the script has authorization for Drive or Gmail if you save or email the blob.
The PDF is blank
Verify that the HTML contains visible body content without relying on client-side JavaScript. Remove external assets temporarily and regenerate the fixture.
Rank #4
Styles are missing
Move critical rules into the document’s embedded <style> block, check HTTPS for active external resources in IFRAME contexts, and test a minimal document before restoring the full template.
Pages overflow or break unexpectedly
Test long content, simplify layout rules, set sensible widths and margins, and inspect the PDF rather than the browser preview. Do not assume a print or page-break rule is honored.
The output is visually unacceptable
Decide whether the requirement is flexible enough for the built-in converter. If not, compare an external renderer using your own samples and review its privacy, operational and contractual terms before sending document data.
Frequently Asked Questions
Does HtmlOutput.getAs(‘application/pdf’) guarantee browser-identical CSS?
No. It is the documented conversion route, but Google does not publish a CSS compatibility matrix for the resulting PDF.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Can I use Google Docs export instead?
Yes, when the report can be represented as a Google Docs document; Document.getAs(‘application/pdf’) is a separate workflow and does not preserve arbitrary HTML/CSS.
What should I test before production use?
Generate representative PDFs and inspect fonts, colors, dimensions, images, page boundaries, long content and overflow after every significant template change.
Quick Recap
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.

