Build a Slides-to-images exporter
Convert each slide to a PNG for the web — for Northwind's social posts and blog embeds.
Published Jul 20, 2025
Northwind’s marketing team builds most of their long-form content in Google Slides — quarterly reviews, case studies, conference talks — but the assets that actually ship are PNGs: one image per slide, embedded in blog posts, sliced into LinkedIn carousels, dropped into Instagram stories. Exporting them by hand means opening the deck, clicking File, Download, PNG, repeating for every slide, then renaming the files so they sort in order. For a 30-slide deck it is half an hour of clicking.
This script does the whole job in one pass. It walks the deck, hits the internal PNG export endpoint for each slide, and drops the results into a Drive folder with zero-padded filenames so they sort the way you’d expect. The endpoint isn’t part of the public Slides API, but it is the same URL the browser uses when you export from the menu — so the output matches what a designer would download by hand.
What you’ll need
- A Google Slides deck to export.
- A Drive folder to receive the PNGs — the script will not create one for you.
- Nothing else —
UrlFetchAppand the script’s own OAuth token do the work.
The script
// The slide export endpoint isn't part of the public Slides API, but it is
// the same URL the Slides UI calls when you choose File > Download > PNG.
const EXPORT_URL = 'https://docs.google.com/presentation/d/{deckId}/export/png';
/**
* Exports every slide in a deck as a PNG into a Drive folder.
* Filenames are zero-padded so they sort in slide order.
*
* @param {string} deckId The Slides file ID.
* @param {string} outputFolderId The Drive folder to write the PNGs into.
*/
function exportSlidesAsPng(deckId, outputFolderId) {
if (!deckId || !outputFolderId) {
throw new Error('exportSlidesAsPng needs both a deckId and an outputFolderId.');
}
const deck = SlidesApp.openById(deckId);
const folder = DriveApp.getFolderById(outputFolderId);
// The export endpoint is private, so we pass the script's own OAuth token
// as a Bearer header — the same credential Slides itself would use.
const token = ScriptApp.getOAuthToken();
const slides = deck.getSlides();
slides.forEach((slide, i) => {
// 1. Build the per-slide export URL. `pageid` is the slide's object ID.
const url = EXPORT_URL.replace('{deckId}', deckId)
+ `?id=${deckId}&pageid=${slide.getObjectId()}`;
// 2. Fetch the PNG bytes. muteHttpExceptions lets us surface a clearer
// error than the default 4xx/5xx exception.
const response = UrlFetchApp.fetch(url, {
headers: { Authorization: `Bearer ${token}` },
muteHttpExceptions: true,
});
if (response.getResponseCode() !== 200) {
Logger.log(`Slide ${i + 1} failed: HTTP ${response.getResponseCode()}.`);
return;
}
// 3. Rename the blob so the file lands in Drive with a tidy name.
// Zero-padding keeps "slide-09" before "slide-10" in any sort.
const name = `slide-${String(i + 1).padStart(2, '0')}.png`;
const blob = response.getBlob().setName(name);
folder.createFile(blob);
});
Logger.log(`Exported ${slides.length} slides to folder ${outputFolderId}.`);
}
/**
* Convenience wrapper so you can run the script from the editor without
* passing arguments. Replace the IDs with your own.
*/
function exportNorthwindDeck() {
exportSlidesAsPng('1abcDeckId', '1abcFolderId');
}
How it works
exportSlidesAsPngguards against missing arguments — the script editor happily passesundefinedif you click Run without picking a wrapper, and the resulting error message is much clearer than a stack trace from deep insideSlidesApp.- It opens the deck and the destination folder, then grabs the script’s own OAuth token. That token is what authenticates the unofficial export endpoint — the same one the Slides UI uses for File, Download, PNG.
- For each slide it builds an export URL using the deck ID and the slide’s
objectId, then fetches the PNG bytes with the Bearer token in the header. - If the response is not a 200, it logs which slide failed and moves on instead of crashing the whole run — a single bad slide should not throw away the other 29.
- It renames the blob to
slide-NN.pngwith zero padding so the files sort in slide order in Drive, Finder, or anywhere else, then writes the file into the output folder. exportNorthwindDeckis a zero-argument wrapper so you can click Run in the editor without writing a temporary caller.
Example run
Say 1abcDeckId is a 12-slide quarterly review and 1abcFolderId is an empty
Drive folder. After one run, the folder contains:
| Filename | Size (typical) |
|---|---|
| slide-01.png | 184 KB |
| slide-02.png | 213 KB |
| slide-03.png | 167 KB |
| … | … |
| slide-12.png | 248 KB |
The log shows Exported 12 slides to folder 1abcFolderId. and the files are
ready to drop into a blog post, a LinkedIn carousel, or a press kit.
Run it
This is an on-demand job — you run it when a deck is final, not on a schedule:
- In the Apps Script editor, select
exportNorthwindDeckand click Run. - Approve the authorisation prompt the first time — the script needs access to Slides, Drive, and external requests.
- Open the output folder in Drive to grab the PNGs.
If different teams export different decks, give each team a thin wrapper function with their own deck ID and folder ID rather than editing the constants every time.
Watch out for
- The export URL is undocumented. It has been stable for years and the Slides UI uses it, but Google could change it without notice. If a run suddenly starts returning HTML instead of PNG bytes, check whether the endpoint moved before assuming the script is broken.
- Each slide is one HTTP call. A 60-slide deck makes 60 round-trips and can take a minute or two. For very large decks, run during quiet hours or split the deck and run the exporter twice.
- The script does not clear the output folder. Run it twice in a row and you
get two copies of
slide-01.pngside by side. Either point each run at a fresh folder or delete the previous files first. - Speaker notes and hidden slides are included. If you only want visible
content, filter with
slide.isSkipped()before calling the export URL.
Related
Auto-publish a deck as an embeddable web page
Push a Northwind deck live after approval — set it to publish-to-web automatically.
Updated Jan 11, 2026
Build a Slide-to-PDF handout generator
Export a clean, notes-included PDF of a Northwind deck for handouts.
Updated Oct 19, 2025
Build a deck accessibility checker
Flag missing alt text, low contrast, and tiny fonts across a Northwind deck.
Updated Dec 14, 2025
Extract all deck text into a sheet
Pull text out of every slide for review, translation, or copy-editing.
Updated Jan 4, 2026
Generate sales-enablement decks per segment
Tailor Northwind's messaging slides by audience segment — fintech, healthcare, retail.
Updated Dec 28, 2025