Is there a way to render html to image like PNG? I know that it is possible with canvas but I would like to render standard html element like div for example.
-
To create some sort of user assistance, for example. Sadly, that's not possible (for security reasons?). You have to ask the user to press PrintScreen in order to do something. – MaxArt May 23 '12 at 14:21
-
1possible duplicate of [How to convert HTML of a website to an image?](http://stackoverflow.com/questions/3960881/how-to-convert-html-of-a-website-to-an-image) – Ernest Friedman-Hill May 23 '12 at 14:24
-
I want to use HTML/CSS to design a logo. – Martin Delille Jun 11 '12 at 05:04
-
5@ErnestFriedman-Hill not a duplicate: the question you mentioned is specific to java. – Martin Delille Jun 11 '12 at 05:07
-
Everyone will know it's possible on the server side. It's the equivalent of answering "What's 2+2?" with "5 is close to what you are looking for, but it's somewhat convoluted." – JayB Oct 01 '16 at 14:56
-
Canvas > dataURL > Image example http://www.freakyjolly.com/convert-html-document-into-image-jpg-png-from-canvas/ – Code Spy Jun 08 '18 at 09:35
21 Answers
There is a lot of options and they all have their pro and cons.
Option 1: Use an API
- ApiFlash (based on chrome)
- EvoPDF (has an option for html)
- Grabzit
- HTML/CSS to Image API
- ...
Pros
- Execute Javascript
- Near perfect rendering
- Fast when caching options are correctly used
- Scale is handled by the APIs
- Precise timing, viewport, ...
- Most of the time they offer a free plan
Cons
- Not free if you plan to use them a lot
Option 2: Use one of the many available libraries
- dom-to-image
- wkhtmltoimage (included in the wkhtmltopdf tool)
- IMGKit (for ruby and based on wkhtmltoimage)
- imgkit (for python and based on wkhtmltoimage)
- python-webkit2png
- ...
Pros
- Conversion is quite fast most of the time
Cons
- Bad rendering
- Does not execute javascript
- No support for recent web features (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Media Queries, ...)
- Sometimes not so easy to install
- Complicated to scale
Option 3: Use PhantomJs and maybe a wrapper library
- PhantomJs
- node-webshot (javascript wrapper library for PhantomJs)
- ...
Pros
- Execute Javascript
- Quite fast
Cons
- Bad rendering
- No support for recent web features (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Media Queries, ...)
- Complicated to scale
- Not so easy to make it work if there is images to be loaded ...
Option 4: Use Chrome Headless and maybe a wrapper library
- Chrome Headless
- chrome-devtools-protocol
- Puppeteer (javascript wrapper library for Chrome headless)
- ...
Pros
- Execute Javascript
- Near perfect rendering
Cons
- Not so easy to have exactly the wanted result regarding:
- page load timing
- viewport dimensions
- Complicated to scale
- Quite slow and even slower if the html contains external links
Disclosure: I'm the founder of ApiFlash. I did my best to provide an honest and useful answer.

- 9,652
- 2
- 56
- 65
-
wkhtmltoimage/pdf does support javascript rendering. You can set a javascript delay or let wkhtml check for a specifc window.status (which you can set with javascript when you know your js stuff is done) – Daniel Z. Apr 05 '18 at 09:16
-
PhantomJS supports dynamic stuff like Google Maps. It's really a full web browser, just without a display attached. However you have to wait a bit for Google Map to load the tiles with the geography (I wait 500ms and allow people to change the delay - if it's not enough, running again without increasing the time is fine, because those tiles are cached). – Ladislav Zima Jan 06 '20 at 10:31
-
1API Flash able to grab the entire webpage if `&full_page=true` is added to the url. Retains its clarity better than many other options I have tried and renders fairly complicated pages well. – Steve May 31 '22 at 17:53
-
A gotcha with many of these techniques is system and monitor dependent font rendering. Ideally you do not want hinting or subpixel antialiasing. I understand OSX has both disabled out of the box. These are often enabled on Linux systems but can be disabled. Windows also has them enabled but I found no clear way to disable them. But, this might not matter at all for you application. – goertzenator Apr 19 '23 at 18:10
May I recommend dom-to-image library, that was written solely to address this problem (I'm the maintainer).
Here is how you use it (some more here):
var node = document.getElementById('my-node');
domtoimage.toPng(node)
.then (function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});

- 2,875
- 3
- 18
- 21
-
2
-
-
My image is created nicely, but I want to be able to print it out at high-resolution, so I need the outputted png to be 2 or 3 times bigger than the DOM element it was rendered from. Is this possible? – cronoklee Feb 11 '16 at 16:21
-
2First thing that comes to my mind - try to render your image to SVG (using `domtoimage.toSvg`), then render it yourself on canvas and try to play with that canvas' resolution somehow. It's probably possible to implement such feature as some kind of rendering option in the lib itself, so you can pass image dimensions in pixels. If you need it, I'd appreciate you creating an issue on github. – tsayen Feb 12 '16 at 09:14
-
Thanks, I've added an issue on github. The easiest way would be to add CSS `zoom:2` on the element before rendering which does work, but it unfortunately crops the image to the original dimensions rather than the new dimensions – cronoklee Feb 12 '16 at 11:14
-
16
-
I found this much better and easy to work with compared to [IMGKit](https://github.com/csquared/IMGKit) on my Rails 4 app. – Jignesh Gohel Aug 11 '16 at 22:32
-
trying to use this library but its printing the textarea and not an image of the HTML. Little confused with how to do this... – Kai McKenzie Oct 24 '16 at 20:47
-
-
1
-
I didn't find this one to be better than html2canvas. The output I kept receiving was nowhere near the actual page visuals. – adamj Apr 16 '17 at 03:03
-
For me (I am using angularJS) dom-to-image library worked better than html2canvas, because both were able to "catch" the div, but only this was able to catch the image inside the div (such an image was within a directive, I don't know whether this is the reason or not). – FtheBuilder Feb 18 '18 at 03:14
-
2Is it possible to use this library, node js server side itself to generate image before it comes to browser? – Kiran Feb 20 '18 at 13:32
-
@tsayen I know this an old thread, but I'm using your amazing lib on a mobile project, but the phone keep showing the rendered images on low resolution. I open them on my pc, but they're perfect. Just on the phone. Is there's anything I'm making wrong? The quality attribute is already on 100... :'( – Rafael de Castro Feb 28 '18 at 18:01
-
Found this to work well. Also see https://github.com/eligrey/FileSaver.js/ and http://stuk.github.io/jszip/ for downloading/zipping. – maltem-za Mar 26 '18 at 15:51
-
Hi would you mind commenting on the robustness of inlining images in SVG docs? Articles seem to indicate it's not very robust because even new browsers have limits on data URIs. If you cap images at 2 MB, could you rely on a client solution to generate PNGs from SVG docs? Or do you have to go server side? Thanks for any insight you can offer! – Crashalot Dec 31 '18 at 23:53
-
I was looking for everywhere for a solution with transparent background. This is much better! – Luke Vo Jun 25 '19 at 10:09
-
-
-
1@tsayen - the project/repo is currently dead? Because on github I see many nice pull requests but nobody merge it – Kamil Kiełczewski Dec 21 '20 at 16:16
-
@KamilKiełczewski I'm not developing this project currently. But the code is open, anyone can fork it and merge all those pull requests – tsayen Feb 16 '21 at 22:58
-
i have a responsive html element which spreads and shrinks with window size. can I download it to an image at its original size? – asif.ibtihaj Oct 12 '21 at 02:21
-
-
@Kiran, I was also interested in creating images on the node side. Would you be able to solve this? Thank You! – ddsultan Jan 31 '22 at 08:04
-
-
-
@Kiran Thanks for the feedback. I used [node-canvas](https://github.com/Automattic/node-canvas) module – ddsultan Feb 25 '22 at 21:23
Yes. HTML2Canvas exists to render HTML onto <canvas>
(which you can then use as an image).
NOTE: There is a known issue, that this will not work with SVG

- 1,536
- 1
- 14
- 29

- 152,115
- 15
- 115
- 172
-
It seems interesting but I didn't manage to make it work so I choose John Fisher solution. Thanks for the info, I'll watch this project in the future! – Martin Delille Jun 07 '12 at 22:04
-
4dom-to-image (see tsayen's answer) does a much better job to render an accurate picture. – JBE May 06 '16 at 13:44
-
-
4
-
3another issue, if the element is hidden or behind another element this will not work – Yousef Sep 07 '17 at 15:25
-
-
This is a good demo for anyone dealing with SVG to image https://codepen.io/samthor/pen/jpPJZP?editors=0010 – Shan Eapen Koshy May 26 '20 at 05:26
-
I've tried dom-to-image, it did not work at all. Had to screenshot HTML with WebGL content in it (Mapbox map), Tried dom-to-image and rasterizeHTML, neither worked. html2canvas worked perfectly – bumbeishvili Nov 25 '21 at 18:48
-
All the answers here use third party libraries while rendering HTML to an image can be relatively simple in pure Javascript. There is was even an article about it on the canvas section on MDN.
The trick is this:
- create an SVG with a foreignObject node containing your XHTML
- set the src of an image to the data url of that SVG
drawImage
onto the canvas- set canvas data to target image.src
const {body} = document
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = canvas.height = 100
const tempImg = document.createElement('img')
tempImg.addEventListener('load', onTempImageLoad)
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><style>em{color:red;}</style><em>I</em> lick <span>cheese</span></div></foreignObject></svg>')
const targetImg = document.createElement('img')
body.appendChild(targetImg)
function onTempImageLoad(e){
ctx.drawImage(e.target, 0, 0)
targetImg.src = canvas.toDataURL()
}
Some things to note
- The HTML inside the SVG has to be XHTML
- For security reasons the SVG as data url of an image acts as an isolated CSS scope for the HTML since no external sources can be loaded. So a Google font for instance has to be inlined using a tool like this one.
- Even when the HTML inside the SVG exceeds the size of the image it wil draw onto the canvas correctly. But the actual height cannot be measured from that image. A fixed height solution will work just fine but dynamic height will require a bit more work. The best is to render the SVG data into an iframe (for isolated CSS scope) and use the resulting size for the canvas.

- 2,468
- 1
- 31
- 33
-
1Nice! Removing external library dependency is indeed the good way to go. I changed my accepted answer :-) – Martin Delille Oct 31 '18 at 16:19
-
-
Strange, does't look moved but simply deleted. I'll try and replace it with a waybackmachine url when I find a computer. – Sjeiti Nov 22 '18 at 14:03
-
4Great answer, but commenting on the state of art of HTML and Web APIs, which as usual looks like something pulled out someones behind -- all the functionality is technically there but exposed behind an array (no pun intended) of weird code paths that resemble nothing of the kind of clarity you would expect from a well designed APIs. In plainspeak: it is most likely trivial for a browser to allow a `Document` to be rendered into a raster (e.g. a `Canvas`), but because noone bothered to standardize it, we have to resort to insanity like illustrated above (no offense at the author of this code). – Armen Michaeli Nov 22 '18 at 14:30
-
Could you comment on the robustness of inlining images in a SVG doc? Articles seem to indicate it's not very robust because even new browsers have limits on data URIs. If you cap images at 2 MB, could you rely on a client solution to generate PNGs from SVG docs? Or do you have to go server side? Thanks for any insight you can offer! – Crashalot Dec 31 '18 at 23:52
-
1This answer https://stackoverflow.com/questions/12637395/what-is-the-size-limit-of-a-base64-dataurl-image/12637435 seems to indicate you can go quite far. Mozilla and Chrome have unlimited data uri lenght and even current IE allows 4GB, which boils down to about 3GB images (due to base64). But this would be a good thing to test. – Sjeiti Jan 01 '19 at 14:14
-
5- some quick and dirty tests later - http://jsfiddle.net/Sjeiti/pcwudrmc/75965/ Chrome, Edge and Firefox go up to a width height of at least 10,000 pixels which (in this case) is a character count of about 10,000,000 and a png filesize of 8MB. Haven't tested rigourously but it's enough for most use cases. – Sjeiti Jan 01 '19 at 15:20
I know this is quite an old question which already has a lot of answers, yet I still spent hours trying to actually do what I wanted:
- given an html file, generate a (png) image with transparent background from the command line
Using Chrome headless (version 74.0.3729.157 as of this response), it is actually easy:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless --screenshot --window-size=256,256 --default-background-color=0 button.html
Explanation of the command:
- you run Chrome from the command line (here shown for the Mac, but assuming similar on Windows or Linux)
--headless
runs Chrome without opening it and exits after the command completes--screenshot
will capture a screenshot (note that it generates a file calledscreenshot.png
in the folder where the command is run)--window-size
allow to only capture a portion of the screen (format is--window-size=width,height
)--default-background-color=0
is the magic trick that tells Chrome to use a transparent background, not the default white color- finally you provide the html file (as a url either local or remote...)

- 2,932
- 1
- 23
- 25
-
2Very nice! It works with SVG also! I switched to your solution in the end! ;-) – Martin Delille Jul 03 '19 at 18:16
-
2
-
3comman line worked. if i want to run this programatically from express js how to run it? – Squapl Recipes Feb 11 '20 at 16:01
-
FYI this also works with chromium even though it doesn't mention the option in the man page. – Robin Zimmerman Apr 20 '20 at 07:58
-
The svg isn't an svg for me ... it's just a PNG with an SVG extension ... so watch out. – kristopolous May 08 '20 at 22:08
-
@kristopolous I don't believe ths is wat Martin Delille is suggesting. You can use Crhome to convert an SVG to a PNG. But not to render a webppage as SVG. – Ideogram Oct 15 '20 at 14:02
You could use PhantomJS, which is a headless webkit (the rendering engine in safari and (up until recently) chrome) driver. You can learn how to do screen capture of pages here. Hope that helps!

- 2,744
- 2
- 25
- 24

- 166
- 1
- 3
-
This technique works well. However, 2 years have passed since your comment. Have you come across anything that operates faster than PhantomJS? Image Generation typically takes 2-5 seconds in Phantom, in my experience. – Brian Webster Dec 14 '15 at 22:16
-
Headless Chrome is now possible. I don't know if it's faster, but if you want accurate screenshots, this is a good way to go. – Josh Maag Aug 08 '17 at 16:32
The only library that I got to work for Chrome, Firefox and MS Edge was rasterizeHTML. It outputs better quality that HTML2Canvas and is still supported unlike HTML2Canvas.
Getting Element and Downloading as PNG
var node= document.getElementById("elementId");
var canvas = document.createElement("canvas");
canvas.height = node.offsetHeight;
canvas.width = node.offsetWidth;
var name = "test.png"
rasterizeHTML.drawHTML(node.outerHTML, canvas)
.then(function (renderResult) {
if (navigator.msSaveBlob) {
window.navigator.msSaveBlob(canvas.msToBlob(), name);
} else {
const a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = canvas.toDataURL();
a.download = name;
a.click();
document.body.removeChild(a);
}
});

- 141
- 1
- 6
-
2but it doesn't work with IE. [rasterizeHTML Limitations](https://github.com/cburgmer/rasterizeHTML.js/wiki/Limitations) – Boban Stojanovski Feb 15 '17 at 21:48
-
-
This change helped me a lot: `rasterizeHTML.drawHTML(node.innerHTML, canvas)` Note that Im calling innerHTML on the node – Sepehr GH Oct 21 '19 at 19:08
-
@MahdiKhalili - https://cburgmer.github.io/rasterizeHTML.js/rasterizeHTML.allinone.js – szmegma May 07 '22 at 17:28
You can use an HTML to PDF tool like wkhtmltopdf. And then you can use a PDF to image tool like imagemagick. Admittedly this is server side and a very convoluted process...

- 35,165
- 3
- 73
- 81
-
14Or you could just run wkhtmltopdf's image brother, wkhtmltoimage. – Roman Starkov Apr 16 '15 at 11:34
-
1
I read the answer by Sjeiti which I found very interesting, where you with just a few plain JavaScript lines can render HTML in an image.
We of course have to be aware of the limitations of this method (please read about some of them in his answer).
Here I have taken his code a couple of steps further.
An SVG-image has in principle infinite resolution, since it is vector graphics. But you might have noticed that the image that Sjeiti's code generated did not have a high resolution. This can be fixed by scaling the SVG-image before transferring it to the canvas-element, which I have done in the last one of the two (runnable) example codes i give below. The other thing I have implemented in that code is the last step, namely saving it as a PNG-file. Just to complete the whole thing.
So, I give two runnable snippets of code:
The first one demonstrates the infinite resolution of an SVG. Run it and zoom in with your browser to see that the resolution does not diminish as you zoom in.
In the snippet that you can run I have used backticks to specify a so called template string with line breaks so that you can more clearly see the HTML that is rendered. But otherwise, if that HTML is within one line, then the code will be very short, like this.
const body = document.getElementsByTagName('BODY')[0];
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;"><style>em {color:red;}.test {color:blue;}</style>What you see here is only an image, nothing else.<br /><br /><em>I</em> really like <span class="test">cheese.</span><br /><br />Zoom in to check the resolution!</div></foreignObject></svg>`);
body.appendChild(img);
Here it comes as a runnable snippet.
const body = document.getElementsByTagName('BODY')[0];
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
Zoom in to check the resolution!
</div>
</foreignObject>
</svg>
`);
body.appendChild(img);
Zoom in and check the infinite resolution of the SVG.
The next runnable, below, is the one that implements the two extra steps which I mentioned above, namely improving resolution by first scaling the SVG, and then the saving as a PNG-image.
window.addEventListener("load", doit, false)
var canvas;
var ctx;
var tempImg;
function doit() {
const body = document.getElementsByTagName('BODY')[0];
const scale = document.getElementById('scale').value;
let trans = document.getElementById('trans').checked;
if (trans) {
trans = '';
} else {
trans = 'background-color:white;';
}
let source = `
<div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;${trans}">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
<div style="text-align:center;">
Scaling:
<br />
${scale} times!
</div>
</div>`
document.getElementById('source').innerHTML = source;
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
canvas.width = 200*scale;
canvas.height = 200*scale;
tempImg = document.createElement('img');
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="${200*scale}" height="${200*scale}">
<foreignObject
style="
width:200px;
height:200px;
transform:scale(${scale});
"
>` + source + `
</foreignObject>
</svg>
`);
}
function saveAsPng(){
ctx.drawImage(tempImg, 0, 0);
var a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'image.png';
a.click();
}
<table border="0">
<tr>
<td colspan="2">
The claims in the HTML-text is only true for the image created when you click the button.
</td>
</tr>
<tr>
<td width="250">
<div id="source" style="width:200px;height:200px;">
</div>
</td>
<td valign="top">
<div>
In this example the PNG-image will be squarish even if the HTML here on the left is not exactly squarish. That can be fixed.<br>
To increase the resolution of the image you can change the scaling with this slider.
<div style="text-align:right;margin:5px 0px;">
<label style="background-color:#FDD;border:1px solid #F77;padding:0px 10px;"><input id="trans" type="checkbox" onchange="doit();" /> Make it transparent</label>
</div>
<span style="white-space:nowrap;">1<input id="scale" type="range" min="1" max="10" step="0.25" value="2" oninput="doit();" style="width:150px;vertical-align:-8px;" />10 <button onclick="saveAsPng();">Save as PNG-image</button></span>
</div>
</td>
</tr>
</table>
Try with different scalings. If you for example set scaling to 10, then you get a very good resolution in the generated PNG-image. And I added a little extra feature: a checkbox so that you can make the PNG-image transparent if you like.
Notice:
The Save-button does not work in Chrome and Edge when this script is run here at Stack Overflow. The reason is this https://www.chromestatus.com/feature/5706745674465280 .
Therefore I have also put this snippet on https://jsfiddle.net/7gozdq5v/ where it works for those browsers.

- 1,584
- 19
- 14
-
You just omitted the main part of the task: converting to PNG! Your image is an SVG, a vector graphics format which is zoomable infinitely. But that is not the question. – MGM Oct 04 '20 at 18:52
-
MGM, You are right. It seems I totally missed that important aspect of the question. I will try to fix my answer so that it covers that part also. Give me some time for that. – Magnus Oct 05 '20 at 19:35
-
-
@Magnus I really love this solution. I was testing on my own and tried adding a background image to the html that's being transformed but found that the image itself doesn't render as the background when being transformed. Any ideas on how that can be fixed? Here's what I tried ``– Zak DeBrine Apr 01 '21 at 23:23
-
@ZakDeBrine I am not able to dive into that problem now, unfortunately. I suggest that you formulate it into a new question to see if you can get some help with it. Good luck! – Magnus Apr 03 '21 at 12:11
Use html2canvas just include plugin and call method to convert HTML to Canvas then download as image PNG
html2canvas(document.getElementById("image-wrap")).then(function(canvas) {
var link = document.createElement("a");
document.body.appendChild(link);
link.download = "manpower_efficiency.jpg";
link.href = canvas.toDataURL();
link.target = '_blank';
link.click();
});
Source: http://www.freakyjolly.com/convert-html-document-into-image-jpg-png-from-canvas/

- 9,626
- 4
- 66
- 46
-
1Please note that html2canvas is having an issue with Shadow dom elements. if your application is using the shadow dom elements and you want it in generated snapshots then html2-canvas is not good choice for you go with html-to-image – Rahul Tokase Feb 01 '22 at 09:56
Use this code, it will surely work:
<script type="text/javascript">
$(document).ready(function () {
setTimeout(function(){
downloadImage();
},1000)
});
function downloadImage(){
html2canvas(document.querySelector("#dvContainer")).then(canvas => {
a = document.createElement('a');
document.body.appendChild(a);
a.download = "test.png";
a.href = canvas.toDataURL();
a.click();
});
}
</script>
Just do not forget to include Html2CanvasJS file in your program. https://html2canvas.hertzen.com/dist/html2canvas.js

- 247
- 2
- 7
I don't expect this to be the best answer, but it seemed interesting enough to post.
Write an app that opens up your favorite browser to the desired HTML document, sizes the window properly, and takes a screen shot. Then, remove the borders of the image.

- 22,355
- 2
- 39
- 64
-
Same as the Headless Chrome Screenshot solution, with the exception of considerable contribution to global warming. – Bahram Ardalan Nov 27 '21 at 03:57
-
-
When an answer is such fundamentally correct and relevant after 9 years that you omit the date (: – Bahram Ardalan Feb 08 '22 at 19:21
-
@BahramArdalan: The date is provided by StackOverflow. Look at the bottom-right area of the answer. It says "answered May 23 2012". – John Fisher Feb 15 '22 at 22:01
-
1Read it again. It was a compliment to you. 'you' was metaphorically meant to be 'me' omitting the date (not looking for it hence not seeing it) because after all these times passed by your perfect answer still seemed so relevant that I didn't think once to check the date. – Bahram Ardalan Feb 18 '22 at 08:07
You can't do this 100% accurately with JavaScript alone.
There's a Qt Webkit tool out there, and a python version. If you want to do it yourself, I've had success with Cocoa:
[self startTraverse:pagesArray performBlock:^(int collectionIndex, int pageIndex) {
NSString *locale = [self selectedLocale];
NSRect offscreenRect = NSMakeRect(0.0, 0.0, webView.frame.size.width, webView.frame.size.height);
NSBitmapImageRep* offscreenRep = nil;
offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:offscreenRect.size.width
pixelsHigh:offscreenRect.size.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:0
bytesPerRow:(4 * offscreenRect.size.width)
bitsPerPixel:32];
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
[NSGraphicsContext setCurrentContext:bitmapContext];
[webView displayRectIgnoringOpacity:offscreenRect inContext:bitmapContext];
[NSGraphicsContext restoreGraphicsState];
// Create a small + large thumbs
NSImage *smallThumbImage = [[NSImage alloc] initWithSize:thumbSizeSmall];
NSImage *largeThumbImage = [[NSImage alloc] initWithSize:thumbSizeLarge];
[smallThumbImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];
NSBitmapImageRep *smallThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];
[smallThumbImage unlockFocus];
[largeThumbImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];
NSBitmapImageRep *largeThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];
[largeThumbImage unlockFocus];
// Write out small
NSString *writePathSmall = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_small.png", locale, collectionIndex, pageIndex]];
NSData *dataSmall = [smallThumbOutput representationUsingType:NSPNGFileType properties: nil];
[dataSmall writeToFile:writePathSmall atomically: NO];
// Write out lage
NSString *writePathLarge = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_large.png", locale, collectionIndex, pageIndex]];
NSData *dataLarge = [largeThumbOutput representationUsingType:NSPNGFileType properties: nil];
[dataLarge writeToFile:writePathLarge atomically: NO];
}];
Hope this helps!

- 1,101
- 17
- 31

- 2,493
- 19
- 25
-
Do you have swift version of the above? or if possible can you please re-write it? – ssh Jun 17 '17 at 14:51
-
Would you mind sharing the code you use to load the webView that you're rendering? This seems like a promising approach for my thumbnail renderer. Thanks! – Dave Apr 14 '18 at 04:23
I also put my head around this issue. And I found this as the best solution for your problem
We can use html-to-image
library of javascript to convert HTML code to image
npm install html-to-image
HTML Code
<div>
<div id="capture">
<p>
<span>Heading Of Image</span><br></br>
<span>This is color Image</span><br></br>
<img src="Your/ImagePath/ifany.jpg" width="100%" />
<span>Footer Of the Image</span>
</p>
</div>
<h2>Generated Image</h2>
<div id="real">
</div></div>
Javascript Code
var htmlToImage = require('html-to-image');
var node = document.getElementById('capture');
htmlToImage.toJpeg(node, { quality: 1, backgroundColor: "#FFFFFF", height: node.clientHeight, width: node.clientWidth })
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
var div = document.getElementById("real")
div.appendChild(img)
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
By this example, you can now see your image in <div>
tag where id = 'real'
.
You can now add the save and download or upload image option in code.

- 459
- 6
- 6
-
1I got better and faster results using this library than the others recommended here, thanks. It also avoids the extra step of creating a canvas since it uses an SVG solution with the `
` tag. – perrocallcenter Jun 14 '23 at 00:46 -
-
This is what I did.
Note: Please check App.js for the code.
If you liked it, you can drop a star.✌️
Update:
import * as htmlToImage from 'html-to-image';
import download from 'downloadjs';
import logo from './logo.svg';
import './App.css';
const App = () => {
const onButtonClick = () => {
var domElement = document.getElementById('my-node');
htmlToImage.toJpeg(domElement)
.then(function (dataUrl) {
console.log(dataUrl);
download(dataUrl, 'image.jpeg');
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
};
return (
<div className="App" id="my-node">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a><br></br>
<button onClick={onButtonClick}>Download as JPEG</button>
</header>
</div>
);
}
export default App;

- 457
- 1
- 4
- 16
-
1Please [avoid link only answers](http://meta.stackoverflow.com/tags/link-only-answers/info). Answers that are "barely more than a link to an external site” [may be deleted](http://stackoverflow.com/help/deleted-answers). – Quentin Dec 01 '20 at 16:47
-
1
Install phantomjs
$ npm install phantomjs
Create a file github.js with following code
var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
page.open('http://github.com/', function() {
page.render('github.png');
phantom.exit();
});
Pass the file as argument to phantomjs
$ phantomjs github.js

- 1,327
- 2
- 13
- 26
I will suggest this npm package "html-to-image"
Description: ✂️ Generates an image from a DOM node using HTML5 canvas and SVG.
How to use:
Install
npm install --save html-to-image
Usage
/* ES6 */
import * as htmlToImage from 'html-to-image';
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
Get a PNG image base64-encoded data URL and download it (using download):
htmlToImage.toPng(document.getElementById('my-node'))
.then(function (dataUrl) {
download(dataUrl, 'my-node.png');
});

- 233
- 3
- 10
HtmlToImage.jar will be the simplest way to convert a html into an image

- 59
- 1
- 5
-
1Please [avoid link only answers](http://meta.stackoverflow.com/tags/link-only-answers/info). Answers that are "barely more than a link to an external site” [may be deleted](http://stackoverflow.com/help/deleted-answers). – Quentin Dec 01 '20 at 16:47
With Playwright's page.screenshot() it's super easy to take a screenshot. For example using Python (but it's also available for Node.js, Java and .NET):
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto('https://google.com')
await page.screenshot(path=f'screenshot.png')
await browser.close()

- 298
- 3
- 10
Yes, You can do it with HTML2Canvas library it renders your HTML code to canvas. It gives the option to convert html to an image from a specific div then use canvas2image to download the image locally to your filesystem.
Link the Source Code
html2canvas(document.querySelector('#screenscoot'), {
onrendered: function(canvas) {
// document.body.appendChild(canvas);
return Canvas2Image.saveAsPNG(canvas);
}
});

- 49
- 2
- 16
-
There are so many problems with this library. I have to say it simply just does not work. It will render very basic things . i get border lines and basically no text or css gets rendered at all. – Joshua Robison Jul 09 '23 at 08:40
You can add reference HtmlRenderer to your project and do the following,
string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));

- 11
- 4