I would like to render individual HTML elements into PNGs using Phantom.JS. Does anyone know if this is possible? Also, how would I use Phantom.js to render a page that the user is already looking at?
Asked
Active
Viewed 2.0k times
5 Answers
50
To only render part of a page you need to set the clipRect attribute for the page and then render it.
var clipRect = document.querySelector(selector).getBoundingClientRect();
page.clipRect = {
top: clipRect.top,
left: clipRect.left,
width: clipRect.width,
height: clipRect.height
};
page.render('capture.png');
I don't understand the second part of your question. Phantom.js is headless meaning that there is no actual display that a user is looking at.

Evan R.
- 3,277
- 3
- 16
- 14

jasonlfunk
- 5,159
- 4
- 29
- 39
-
I understand that phantom.js is headless. What I need in particular is its ability to capture a webpage from what's visible in the browser viewport. Do you know of a way to do this? – Dany Joumaa Aug 12 '12 at 06:43
-
Okay, I understand what you mean. I don't know for sure if PhantomJS works that way or not. I don't know if Phantom has any concept of a viewport or anything like that. – jasonlfunk Aug 13 '12 at 00:34
-
1I see. I am looking for some sort of framework that does this or some function inside the chrome extension API that allows me to do this. If you have any pointers, I'd greatly appreciate it. – Dany Joumaa Aug 13 '12 at 19:36
-
What are you trying to do exactly? Is there some javascript that scrolls down that you are trying to test? If it's user interaction that you are trying to simulate, then you can use the approach I mentioned above to render any part of the page and simulate scroll by adjusting the `top` attribute. – jasonlfunk Aug 13 '12 at 20:36
-
I am trying to capture each HTML element on the page and export a PNG for debugging purposes. The only APIs that I know of allow me to take a screenshot of the browser viewport, but provide no support for capturing individual elements or specific rects. – Dany Joumaa Aug 13 '12 at 20:46
-
Oh, I understand. You are looking for a browser implementation of this, not a headless server-side option. – jasonlfunk Aug 14 '12 at 01:17
-
1I'm sorry. I don't know of anything. – jasonlfunk Aug 14 '12 at 02:40
-
25The above example needed `var clipRect = page.evaluate(function () { return document.querySelector("#someid").getBoundingClientRect(); });` when I tried. The evaluate function evaluates document in the context of page. – unhammer Sep 11 '12 at 10:19
-
If I know the size of the image I'm trying to capture ahead of time, even if I set the clipRect to `{top: 0, left: 0, width: 300, height: 250}`, PhantomJS renders a bigger image (the excess is just black #000 pixels). What gives? Is there a minimum image size PhantomJS can render? – chamberlainpi Sep 29 '16 at 20:45
-
^ (continue) this is using "JPEG" export. PNG seems to be fine. – chamberlainpi Sep 29 '16 at 20:53
22
Working example.
var page = require('webpage').create();
page.open('http://google.com', function() {
// being the actual size of the headless browser
page.viewportSize = { width: 1440, height: 900 };
var clipRect = page.evaluate(function(){
return document.querySelector('#hplogo').getBoundingClientRect();
});
page.clipRect = {
top: clipRect.top,
left: clipRect.left,
width: clipRect.width,
height: clipRect.height
};
page.render('google.png');
phantom.exit();
});

Qix - MONICA WAS MISTREATED
- 14,451
- 16
- 82
- 145

mgrachev
- 369
- 2
- 6
5
You can use the CasperJS, another project based on PhantomJS.
casper.start('http://www.weather.com/', function() {
this.captureSelector('weather.png', '#wx-main');
});
casper.run();

Silvio Lucena Junior
- 151
- 1
- 6
0
The solution below works for me.
var clipRect = document.querySelector(selector).getBoundingClientRect();
page.clipRect = {
top: clipRect.top,
left: clipRect.left,
width: clipRect.width,
height: clipRect.height
};
page.render('capture.png');
But I notice that this on works only if we are rendering an image not a pdf. To wokaround this for pdf, try this
page.evaluate(function (element){
$(element).appendTo('body');
$('body > :not(' + element + ')').hide();
}, element);
});
window.setTimeout(function(){
page.render("page.pdf");
},1000);
This links may help: How to hide all elements except one using jquery?
-5
I had the same need, I tried this and it worked fine for me :
don't forget the http://www
in the URL
var page = require('webpage').create();
page.open('YourPageURL', function (status) {
if (status !== 'success') {
console.log('Network Problem');
} else {
var p = page.evaluate(function () {
return document.getElementById('yourDivID').innerHTML
});
console.log(p);
}
phantom.exit();
});

ZinebM
- 109
- 2
- 7
-
2Voted down because that does not actually save a screenshots of "individual HTML elements into PNGs" as stated in the question. It merely prints inner HTML of some element to console. – Val Redchenko Jun 05 '13 at 10:42