Short answer: C3.js does not provide a documented one-click PNG or PDF export API. Render the chart as SVG, serialize that SVG, rasterize it onto a Canvas for PNG, and place the resulting image into a PDF document. The code below waits for the chart to render, preserves its dimensions, and includes checks for the browser conditions that commonly break exports.
What C3.js actually renders
C3.js is a D3-based chart library. Its normal setup loads D3 and C3, binds a chart to an element, and calls c3.generate(). The chart output is SVG-oriented markup inside that element, not a downloadable PNG or PDF file. Export therefore has two stages:
- PNG: SVG serialization, SVG decoding in an
Image, Canvas drawing, then PNG encoding. - PDF: the same PNG step followed by adding the image to a PDF document with a browser PDF library such as jsPDF.
The C3 pages and repository documentation reviewed do not document a native export command. They also show different D3 dependency declarations (the official site lists D3 ^4.12.0, while the repository README lists ^5.0.0), so use the versions installed by your project rather than blindly mixing examples.
Prepare the chart for reliable capture
Use a real, sized container
Give the chart element a nonzero width and height before generating it. A hidden tab, collapsed panel, or container with no layout width can produce an empty Canvas or clipped labels.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
<div id="chart" style="width: 900px; height: 500px"></div>
<button id="pngButton" type="button">Download PNG</button>
<button id="pdfButton" type="button">Download PDF</button>
Generate and flush the chart
Load compatible D3, C3, and the C3 stylesheet as you normally do in your application. Then keep the chart object and explicitly flush it before export. If your data arrives asynchronously, call the export functions only after the data has loaded.
const chart = c3.generate({
bindto: '#chart',
size: { width: 900, height: 500 },
data: {
columns: [
['Sales', 30, 45, 38, 52, 61],
['Refunds', 4, 7, 5, 8, 6]
],
type: 'line'
},
axis: {
x: { type: 'category', categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May'] },
y: { label: { text: 'Amount', position: 'outer-middle' } }
},
legend: { show: true }
});
// Let C3 finish its transitions and layout work.
chart.flush();
For charts that animate, wait until the transition has completed or disable animation for a deterministic capture. Call chart.resize({ width, height }) before exporting when the target dimensions differ from the live chart, and flush again.
Export a C3 chart to PNG
1. Serialize the SVG
The function below finds the chart SVG, copies its current width and height, and serializes it. It also adds an XML namespace when one is missing, which improves decoding in some browsers.
function getChartSvg() {
const svg = document.querySelector('#chart svg');
if (!svg) throw new Error('C3 SVG was not found. Check bindto and render timing.');
const copy = svg.cloneNode(true);
if (!copy.getAttribute('xmlns')) {
copy.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
}
if (!copy.getAttribute('xmlns:xlink')) {
copy.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
}
const rect = svg.getBoundingClientRect();
const width = Math.ceil(rect.width || svg.viewBox.baseVal.width || 900);
const height = Math.ceil(rect.height || svg.viewBox.baseVal.height || 500);
copy.setAttribute('width', String(width));
copy.setAttribute('height', String(height));
const source = new XMLSerializer().serializeToString(copy);
return { source, width, height };
}
2. Convert SVG to a Canvas and download it
Computed CSS and external assets deserve special attention. A cloned SVG does not automatically contain every stylesheet rule that affected the live chart. The example inlines the most important computed presentation properties for SVG elements. If your design depends on complex CSS, inline those rules in your application or add a dedicated export stylesheet.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsRank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
function inlineSvgStyles(sourceSvg) {
const clone = sourceSvg.cloneNode(true);
clone.querySelectorAll('*').forEach((node) => {
const computed = getComputedStyle(node);
const properties = [
'fill', 'fill-opacity', 'stroke', 'stroke-width', 'stroke-opacity',
'font-family', 'font-size', 'font-weight', 'opacity', 'text-anchor'
];
const declarations = properties
.map((name) => {
const value = computed.getPropertyValue(name);
return value ? `${name}:${value}` : '';
})
.filter(Boolean)
.join(';');
if (declarations) node.setAttribute('style', declarations);
});
return clone;
}
function svgToPngBlob() {
const liveSvg = document.querySelector('#chart svg');
if (!liveSvg) return Promise.reject(new Error('No chart SVG found.'));
const styledSvg = inlineSvgStyles(liveSvg);
if (!styledSvg.getAttribute('xmlns')) {
styledSvg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
}
const box = liveSvg.getBoundingClientRect();
const width = Math.ceil(box.width);
const height = Math.ceil(box.height);
if (!width || !height) {
return Promise.reject(new Error('Chart dimensions are zero. Make the container visible and sized.'));
}
styledSvg.setAttribute('width', width);
styledSvg.setAttribute('height', height);
const serialized = new XMLSerializer().serializeToString(styledSvg);
const svgBlob = new Blob([serialized], { type: 'image/svg+xml;charset=utf-8' });
const objectUrl = URL.createObjectURL(svgBlob);
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
try {
const scale = Math.max(1, window.devicePixelRatio || 1);
const canvas = document.createElement('canvas');
canvas.width = Math.round(width * scale);
canvas.height = Math.round(height * scale);
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
const context = canvas.getContext('2d');
if (!context) throw new Error('Canvas 2D is unavailable.');
context.scale(scale, scale);
context.drawImage(image, 0, 0, width, height);
canvas.toBlob((blob) => {
URL.revokeObjectURL(objectUrl);
if (blob) resolve({ blob, width, height });
else reject(new Error('Canvas could not encode a PNG.'));
}, 'image/png');
} catch (error) {
URL.revokeObjectURL(objectUrl);
reject(error);
}
};
image.onerror = () => {
URL.revokeObjectURL(objectUrl);
reject(new Error('The browser could not decode the serialized SVG.'));
};
image.src = objectUrl;
});
}
function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
setTimeout(() => URL.revokeObjectURL(url), 1000);
}
document.querySelector('#pngButton').addEventListener('click', async () => {
chart.flush();
const { blob } = await svgToPngBlob();
downloadBlob(blob, 'c3-chart.png');
});
The scale factor improves sharpness on high-density displays, but it also multiplies memory use. For very large charts, choose a fixed scale such as 2 and test the resulting pixel dimensions.
Export the chart to PDF
A browser PDF library adds the PNG to a document; C3 itself does not create the PDF. The following example assumes jsPDF is loaded by your application and available as window.jspdf.jsPDF. It fits the image inside a landscape A4 page while preserving its aspect ratio.
async function downloadChartPdf() {
chart.flush();
const { blob, width, height } = await svgToPngBlob();
const dataUrl = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
const JsPDF = window.jspdf && window.jspdf.jsPDF;
if (!JsPDF) throw new Error('jsPDF is not loaded.');
const pdf = new JsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
const margin = 36;
const availableWidth = pageWidth - margin * 2;
const availableHeight = pageHeight - margin * 2;
const ratio = Math.min(availableWidth / width, availableHeight / height);
const drawWidth = width * ratio;
const drawHeight = height * ratio;
const x = (pageWidth - drawWidth) / 2;
const y = (pageHeight - drawHeight) / 2;
pdf.addImage(dataUrl, 'PNG', x, y, drawWidth, drawHeight);
pdf.save('c3-chart.pdf');
}
document.querySelector('#pdfButton').addEventListener('click', downloadChartPdf);
This raster PDF is convenient for reports, email, and document delivery. Enlarging it beyond the source pixel dimensions can soften text and fine lines. A vector-preserving PDF path would require an SVG-capable PDF workflow; the official C3 material reviewed does not establish a C3-native vector-PDF exporter.
PNG or PDF: choose by the delivery requirement
| Need | PNG | |
|---|---|---|
| Quick sharing in a chat, ticket, or web page | Simple standalone image | Usually unnecessary |
| Document submission or printing | Must be placed in another document | Single file with page layout |
| Scaling | Limited by encoded pixel dimensions | Raster image has the same limitation; vector PDF needs a different export path |
| Implementation | SVG serialization, image decode, Canvas, PNG encoding | All PNG steps plus PDF creation and page sizing |
Fonts, styles, and cross-origin assets
- Fonts: wait until web fonts have loaded if label metrics matter. A fallback font can change wrapping and clipping.
- External images: images referenced by the SVG must be available to the browser and permitted for Canvas use. Cross-origin resources without suitable CORS headers can taint the Canvas, causing
toBlob()ortoDataURL()to fail. - CSS: external stylesheets are not guaranteed to travel with serialized SVG. Inline computed properties or provide export-specific SVG styles.
- Background: Canvas is transparent by default. Paint a background before
drawImage()when a white page is required: setcontext.fillStyle = '#fff'and callfillRect(0, 0, canvas.width, canvas.height)before drawing. - Responsive charts: capture only after the final viewport and container size are established. A resize after serialization will not update an already-created image.
Troubleshooting export failures
“No chart SVG found”
The selector does not match bindto, or export runs before c3.generate() finishes. Confirm that #chart exists, inspect it for an svg child, and trigger export from a user action after rendering.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
Blank or tiny PNG
Check the container’s computed width and height. Hidden tabs often report zero dimensions. Make the panel visible, call chart.resize(), then chart.flush() before conversion.
Missing colors, labels, or legend styling
The live chart receives CSS from stylesheets that the serialized SVG does not include. Inline computed properties, as shown above, and verify the serialized SVG in a temporary image before downloading.
Canvas security or encoding errors
Look for cross-origin images, patterns, or fonts. Host assets with appropriate CORS response headers, use same-origin resources, or remove external assets from the export variant.
PDF content is clipped
Measure the image and page in the same units, reserve margins, and calculate a single fit ratio. For a very wide chart, use landscape orientation or split it across pages rather than stretching it.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Text looks soft in the PDF
The PDF contains a raster image. Increase the Canvas scale before encoding, while watching memory use, or investigate a separate vector-SVG PDF library if selectable, infinitely scalable text is a requirement.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance, reliability, and cost considerations
SVG serialization and Canvas encoding happen on the main thread. Large full-page charts can temporarily consume several times their final file size in memory because the browser holds SVG text, decoded pixels, Canvas pixels, and the encoded Blob. Export on demand, release object URLs, and avoid unnecessarily large scale factors. For repeatable output, set dimensions explicitly, disable animation during capture, wait for fonts and data, and reopen representative PNG and PDF files to inspect clipping, legends, axes, background, and font rendering.
Or skip the browser setup
If the chart is already published at a URL, ScreenshotNeo can capture that page through one request instead of maintaining SVG, Canvas, and PDF browser code. It removes cookie banners, newsletter popups, and chat widgets before the shot. 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 exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
See the ScreenshotNeo documentation for all options. A direct image request looks like this:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/chart.html -o chart.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com/chart.html"},
timeout=90,
)
r.raise_for_status()
open("chart.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com/chart.html'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('chart.webp', data);
ScreenshotNeo includes 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account to try it.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
Frequently Asked Questions
Can I export the C3 SVG directly as a PDF?
Not with a documented C3 command. The workflow above rasterizes the SVG first; a vector PDF requires a separate SVG-capable PDF implementation.
Why does my exported chart differ from the page?
Serialized SVG does not automatically include every computed CSS rule, font, or external asset. Inline required styles, wait for fonts, and test cross-origin resources.
Should I use devicePixelRatio for every export?
It improves sharpness on dense displays but increases Canvas memory and output dimensions. Use a bounded scale for very large charts.
Recommended Free Tools
The Bottom Line
For browser-side C3 exports, treat SVG as the source, Canvas as the PNG conversion step, and a PDF library as the document step. Set dimensions before rendering, wait for completion, account for styles and cross-origin assets, and inspect the files you produce.
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.




