Question
Is it possible to capture or print the content displayed in an HTML <canvas> element as an image or PDF? For example, after generating an image with canvas, how can I export it as a PNG file?
Short Answer
You will learn how canvas pixels can be exported as image data, downloaded as PNG or JPEG files, displayed in an <img> element, and placed into a PDF. You will also learn why GIF export is different and why cross-origin images can prevent exporting.
Concept
An HTML <canvas> is a drawing surface managed by the browser. Although it may contain shapes, text, or images, the canvas itself is not automatically an image file.
JavaScript can ask the browser to encode the current canvas pixels into an image format:
canvas.toDataURL()returns a Base64 data URL string.canvas.toBlob()creates aBlob, which is efficient for downloads, uploads, and object URLs.
PNG is usually the best default because it is lossless and supports transparency. JPEG is smaller for photographic content but does not support transparency. Creating a PDF is normally a separate step: export or use the canvas image data, then insert it into a PDF using a client-side PDF library or generate the PDF on a server.
This matters in applications that create charts, signatures, certificates, image editors, reports, diagrams, and downloadable user-generated content.
Mental Model
Think of a canvas as a whiteboard in a browser.
- Drawing methods such as
fillRect()andfillText()put marks on the whiteboard. toBlob()takes a photograph of the whiteboard and puts that photograph into a file-like container.toDataURL()takes the same photograph but writes it as a long text string.- A PDF is like placing that photograph onto a page in a document.
The export captures the canvas as it looks at that moment. Later changes to the canvas are not included in a file that was already exported.
Syntax and Examples
Use toBlob() when you want a downloadable file or need to upload the result. It avoids creating a large Base64 string in JavaScript memory.
const canvas = document.querySelector("canvas");
canvas.toBlob((blob) => {
if (!blob) {
console.error("Canvas export failed.");
return;
}
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "drawing.png";
link.click();
URL.revokeObjectURL(url);
}, "image/png");
The second argument is the MIME type. Common choices are:
"image/png" // lossless; supports transparency
"image/jpeg" // smaller for photos; no transparency
"image/webp" // supported by many modern browsers
For JPEG or WebP, a third argument can set approximate quality from 0 to 1:
canvas.toBlob(saveFile, "image/jpeg", 0.9);
function saveFile(blob) {
// Use the Blob here.
}
toDataURL() is useful when an API or library explicitly needs a data URL:
const pngDataUrl = canvas.toDataURL("image/png");
console.log(pngDataUrl);
const preview = document.createElement("img");
preview.src = pngDataUrl;
document.body.append(preview);
A data URL begins with text similar to data:image/png;base64,.... It contains the complete image encoded as a string.
Step by Step Execution
Consider this complete example:
<canvas id="art" width="400" height="200"></canvas>
<button id="download">Download PNG</button>
<script>
const canvas = document.querySelector("#art");
const context = canvas.getContext("2d");
context.fillStyle = "#2563eb";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "white";
context.font = "32px sans-serif";
context.fillText("Canvas export", 85, 115);
document.querySelector("#download").addEventListener("click", () => {
canvas.toBlob((blob) => {
if (!blob) return;
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "canvas-art.png";
link.click();
URL.revokeObjectURL(url);
}, "image/png");
});
</script>
Execution flow:
- The
<canvas>element creates a 400 by 200 pixel drawing area. getContext("2d")provides the 2D drawing API.fillRect()paints a blue background.fillText()draws white text over the background.- When the button is clicked,
toBlob()encodes the current pixels as a PNG. URL.createObjectURL()creates a temporary browser URL for that PNG blob.- A temporary
<a>element withdownloadtriggers the file download. URL.revokeObjectURL()releases the temporary URL after it is no longer needed.
Real World Use Cases
Canvas export is common in many browser applications:
- Chart dashboards: Let users download a rendered chart as a PNG for a presentation.
- Signature pads: Save a handwritten signature as a PNG and upload it with a form.
- Image annotation tools: Export an image after users add labels, arrows, or highlights.
- Report generators: Render a chart or diagram and insert it into a PDF report.
- Drawing applications: Save a user's sketch locally or send it to an API.
- Certificate generators: Draw personalized certificate text and decorations, then download the result as an image or PDF.
Real Codebase Usage
In production code, exporting is often wrapped in a reusable function and paired with validation and error handling.
Reusable PNG download helper
function downloadCanvas(canvas, filename = "image.png") {
if (!(canvas instanceof HTMLCanvasElement)) {
throw new TypeError("A canvas element is required.");
}
canvas.toBlob((blob) => {
if (!blob) {
console.error("The browser could not create the image blob.");
return;
}
const link = document.createElement("a");
const url = URL.createObjectURL(blob);
link.href = url;
link.download = filename;
link.click();
setTimeout(() => URL.revokeObjectURL(url), 0);
}, "image/png");
}
Uploading the canvas to an API
Use FormData when the server expects a file upload:
async function uploadCanvas(canvas) {
const blob = await new Promise((resolve) => {
canvas.toBlob(resolve, "image/png");
});
if (!blob) {
throw new Error("Could not export canvas.");
}
const formData = new FormData();
formData.append("image", blob, "drawing.png");
const response = await fetch("/api/images", {
method: "POST",
body: formData
});
if (!response.ok) {
throw new Error("Image upload failed.");
}
}
Creating a PDF
A canvas does not directly become a PDF with the standard Canvas API. A common client-side approach is to use a PDF library, such as jsPDF, and add the canvas image to a page:
// Assumes jsPDF has been loaded by your application.
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: "landscape" });
const image = canvas.toDataURL("image/png");
pdf.addImage(image, "PNG", 10, 10, 270, 135);
pdf.save("report.pdf");
For reports with complex layouts, pagination, or reliable printing, applications may instead send the data to a server that generates the PDF.
Common Mistakes
Assuming canvas export includes surrounding HTML
Only pixels drawn inside the canvas are exported. Buttons, labels, and other DOM elements around it are not included.
canvas.toDataURL(); // Exports only the canvas, not the entire page.
If you need a full page or component capture, use a dedicated DOM-to-image approach or generate a print-specific layout.
Exporting before an image finishes loading
This can produce an empty or incomplete result.
const image = new Image();
image.src = "/photo.png";
context.drawImage(image, 0, 0); // Too early: the image may not be loaded yet.
Wait for onload instead:
const image = new Image();
image.onload = () => {
context.drawImage(image, 0, 0);
canvas.toBlob((blob) => {
// Export after drawing is complete.
}, "image/png");
};
image.src = "/photo.png";
Ignoring cross-origin security restrictions
If you draw an image from another origin without suitable CORS permission, the canvas becomes tainted. Calls such as toDataURL() and toBlob() may throw a SecurityError or fail.
When the remote server permits CORS, set crossOrigin before setting src:
const image = new Image();
image.crossOrigin = "anonymous";
image.onload = () => context.drawImage(image, 0, 0);
image.src = "https://example.com/public-image.png";
The image server must also send an appropriate Access-Control-Allow-Origin header. You cannot fix this only from browser JavaScript if the server does not allow it.
Expecting JPEG to preserve transparency
JPEG has no alpha channel. Transparent regions are flattened, often against black or another browser-chosen background. Use PNG when transparency matters.
Using GIF as a normal canvas export format
Browsers commonly support PNG and JPEG canvas encoding, and may support WebP. GIF is not a standard output type for toBlob() or toDataURL(). Creating an animated GIF typically requires collecting frames and encoding them with a GIF encoder library or on a server.
Forgetting the canvas resolution
The export size comes from canvas.width and canvas.height, not the CSS display size. A canvas displayed at 800 CSS pixels wide can still export at only 400 pixels wide if its internal width is 400.
Comparisons
| Option | Result | Best use | Important note |
|---|---|---|---|
canvas.toBlob() | Blob asynchronously | Downloads, uploads, large images | Preferred default for file workflows |
canvas.toDataURL() | Base64 string synchronously | Image previews and libraries requiring data URLs | Can use substantial memory for large canvases |
| PNG | Lossless image | Text, diagrams, transparency, drawings | Usually larger than JPEG for photos |
| JPEG | Lossy image | Photos where small files matter | Does not support transparency |
| WebP | Modern image format | Smaller image files when supported by your target browsers | Verify browser and backend support |
| GIF | Static or animated image | Legacy/simple animations | Not a standard canvas export output format |
| Document containing image(s) | Reports, printing, multi-page documents | Usually requires a PDF library or server-side generator |
toBlob() and toDataURL() both capture the canvas pixels. The main difference is the form of the result: a file-like binary object versus a text string.
Cheat Sheet
// PNG Blob: preferred for download/upload
canvas.toBlob((blob) => {
// blob may be null, so check it.
}, "image/png");
// JPEG Blob with quality
canvas.toBlob(callback, "image/jpeg", 0.85);
// Base64 data URL
const url = canvas.toDataURL("image/png");
// Download a Blob
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "image.png";
link.click();
URL.revokeObjectURL(url);
- Use PNG for transparency, text, screenshots, and diagrams.
- Use JPEG for smaller photographic images; quality is usually between
0and1. - Prefer
toBlob()for downloads and API uploads. - Canvas export captures only the canvas bitmap, not nearby HTML.
- Wait until all drawing and image loading is complete before exporting.
- Cross-origin images need server-approved CORS headers, or export is blocked.
- GIF encoding is not a standard
toBlob()/toDataURL()output feature. - The internal canvas dimensions control output resolution.
FAQ
How do I save an HTML canvas as a PNG?
Call canvas.toBlob() with "image/png", create an object URL from the blob, and trigger a download with an <a> element.
Is toBlob() better than toDataURL()?
For downloads and uploads, usually yes. toBlob() produces a file-like binary object and does not require keeping a large Base64 string in memory.
Can I convert a canvas to JPEG?
Yes. Use canvas.toBlob(callback, "image/jpeg", quality) or canvas.toDataURL("image/jpeg", quality). JPEG does not retain transparent pixels.
Why does canvas export fail after I draw an external image?
The external image may not have CORS permission. A canvas that contains unapproved cross-origin image data cannot be read back by JavaScript for security reasons.
Can a canvas be exported as an animated GIF?
Not directly with the standard Canvas API. You need to capture multiple canvas frames and use a GIF encoding library or a server-side encoder.
Can I create a PDF from a canvas?
Yes, but usually by adding the exported canvas image to a PDF with a library such as jsPDF, or by sending the image/data to a server-side PDF generator.
Why is my exported image blurry?
The canvas internal width and height may be too small. Increase those pixel dimensions before drawing; CSS size alone does not increase export resolution.
Mini Project
Description
Build a small canvas badge generator. It draws a personalized badge and lets the user download the generated design as a PNG. This mirrors features used in certificate tools, social-media image generators, and simple design applications.
Goal
Create a canvas drawing and export its current contents as a downloadable PNG file.
Requirements
Draw a colored background on a canvas. Add a title and a user-provided name. Redraw the canvas when the user clicks a Generate button. Download the current canvas as a PNG when the user clicks Download PNG. Handle a failed blob export safely.
Keep learning
Related questions
Add a Favicon to a Static HTML Page
Learn how to add a favicon to static HTML pages, use correct paths and icon formats, and troubleshoot browser caching and local-file issues.
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
Apply CSS !important with jQuery .css()
Learn why jQuery .css() cannot set !important and how to use CSSStyleDeclaration.setProperty() to apply inline important styles safely.