How to Convert a Chart.js Chart to a PNG

Render a Chart.js visualization as a static PNG. Useful for reports, dashboards, email digests and printed analytics.

For a deeper walkthrough including server-side rendering, see Server-side Chart.js rendering in Python.

HTML Content

<canvas id="myChart" width="400" height="300"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
  const ctx = document.getElementById('myChart');
  new Chart(ctx, {
    type: 'bar',
    data: {
      labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
      datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        backgroundColor: [
          'rgba(255, 99, 132, 0.5)',
          'rgba(54, 162, 235, 0.5)',
          'rgba(255, 206, 86, 0.5)',
          'rgba(75, 192, 192, 0.5)',
          'rgba(153, 102, 255, 0.5)',
          'rgba(255, 159, 64, 0.5)'
        ],
        borderColor: [
          'rgba(255, 99, 132, 1)',
          'rgba(54, 162, 235, 1)',
          'rgba(255, 206, 86, 1)',
          'rgba(75, 192, 192, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
      }]
    },
    options: {
      animation: false,
      scales: {
        y: {
          beginAtZero: true
        }
      }
    }
  });
</script>

CSS Styles

body {
    margin: 0;
    padding: 16px;
    background: white;
}

canvas {
    display: block;
    margin: 0 auto;
}

API Request

POST https://app.html2img.com/api/html
{
    "html": "<canvas id=\"myChart\" width=\"400\" height=\"300\"></canvas><script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script><script>const ctx = document.getElementById('myChart'); new Chart(ctx, {type: 'bar',data: {labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],datasets: [{label: '# of Votes',data: [12, 19, 3, 5, 2, 3],backgroundColor: ['rgba(255, 99, 132, 0.5)','rgba(54, 162, 235, 0.5)','rgba(255, 206, 86, 0.5)','rgba(75, 192, 192, 0.5)','rgba(153, 102, 255, 0.5)','rgba(255, 159, 64, 0.5)'],borderColor: ['rgba(255, 99, 132, 1)','rgba(54, 162, 235, 1)','rgba(255, 206, 86, 1)','rgba(75, 192, 192, 1)','rgba(153, 102, 255, 1)','rgba(255, 159, 64, 1)'],borderWidth: 1}]},options: {animation: false,scales: {y: {beginAtZero: true}}}});</script>",
    "width": 450,
    "height": 350,
    "css": "body { margin: 0; padding: 16px; background: white; } canvas { display: block; margin: 0 auto; }"
}
Chart to Image Example

The example uses Chart.js, but you can use any JavaScript charting library like D3.js, Highcharts, or ApexCharts.

How it Works

  1. We include Chart.js from CDN and create a canvas element
  2. The chart is configured with static data and options
  3. Animation is disabled to ensure immediate rendering
  4. Padding is added around the canvas for better presentation

For larger charts, use a webhook_url so the chart library has time to load and render before capture.

Code in other languages

Node.js

const response = await fetch('https://app.html2img.com/api/html', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.HTML2IMG_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    html: chartHtml,
    css: chartCss,
    width: 450,
    height: 350,
    wait_for_selector: '#myChart',
    ms_delay: 500,
  }),
});
const { url } = await response.json();

Python

import os, requests
response = requests.post(
    'https://app.html2img.com/api/html',
    headers={'X-API-Key': os.environ['HTML2IMG_API_KEY']},
    json={
        'html': chart_html,
        'css': chart_css,
        'width': 450, 'height': 350,
        'wait_for_selector': '#myChart',
        'ms_delay': 500,
    },
)
url = response.json()['url']

PHP

$ch = curl_init('https://app.html2img.com/api/html');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('HTML2IMG_API_KEY'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'html' => $chartHtml, 'css' => $chartCss,
        'width' => 450, 'height' => 350,
        'wait_for_selector' => '#myChart', 'ms_delay' => 500,
    ]),
]);
$url = json_decode(curl_exec($ch), true)['url'];

Common pitfalls

  • Animations blur the capture. Chart.js animates by default. Set options.animation = false so the chart paints in one frame.
  • Chart.js loads after capture. Pair wait_for_selector with ms_delay to ensure the canvas is drawn.
  • High-DPI rendering looks wrong. Charts can render at 1x even when DPI is 2. Set the canvas size in CSS, not just the width attribute.

See also