screen shot with phantomjs is not accurate as its seeing in browser - javascript

Hi i am working with PhantomJs to capture screen from url. But it seem sresult not accurate.
version of PhantomJS : 1.9.8, Operating system : Ubuntu 14
With this below code i tried to capture screen from a url but it seems its not giving perfect screen shot..
Or i am doing something wrong ?
See on header part of this website and screen shot..both are not similar.
Result screen shot : http://www.awesomescreenshot.com/image/2275399/7cf995d2e287cb87c4ca4895b6b69934
Website which i am trying to capture: http://www.whiteboardexplainers.com/
var system = require("system");
if (system.args.length > 0) {
var page = require('webpage').create();
page.viewportSize = {width: 1280, height: 1024};
page.open(system.args[1], function() {
var pageTitle = system.args[1].replace(/http.*\/\//g, "").replace("www.", "").split("/")[0]
var filePath = "pageTitle + '.png';
window.setTimeout(function () {
page.evaluate(function() {
document.body.bgColor = 'white';
});
page.render(filePath);
console.log(filePath);
phantom.exit();
}, 200);
});
}

You use a very outdated PhantomJS version. Considering that, screnshot looks very good. Upgrade to a modern PhantomJS version: 2.1.1 or even better 2.5 beta. Get them here: PhantomJS downloads archive.
But even a modern version does not support showing videos, so that will not work anyway.
In your case it does not seem relevant but often is: it is advisable to declare a useragent string of a modern browser. Otherwise many sites show a mobile version of their pages.

Related

Can you determine if Chrome(latest versions above 83) is in incognito mode via a script? [duplicate]

Is it possible to determine if Google Chrome is in incognito mode via a script?
Edit: I actually meant is it possible via user-script, but the answers assume JavaScript is running on a web page. I've re-asked the question here in regards to user scripts.
The functionality of this answer is Chrome version dependant. The most recent comment was this works in v90
Yes. The FileSystem API is disabled in incognito mode. Check out https://jsfiddle.net/w49x9f1a/ when you are and aren't in incognito mode.
Sample code:
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
console.log("check failed?");
} else {
fs(window.TEMPORARY,
100,
console.log.bind(console, "not in incognito mode"),
console.log.bind(console, "incognito mode"));
}
In Chrome 74 to 84.0.4147.135 you can determine this by estimating the available file system storage space
See the jsfiddle
if ('storage' in navigator && 'estimate' in navigator.storage) {
const {usage, quota} = await navigator.storage.estimate();
console.log(`Using ${usage} out of ${quota} bytes.`);
if(quota < 120000000){
console.log('Incognito')
} else {
console.log('Not Incognito')
}
} else {
console.log('Can not detect')
}
One way is to visit a unique URL and then check to see whether a link to that URL is treated as visited by CSS.
You can see an example of this in "Detecting Incognito" (Dead link).
Research paper by same author to replace Detecting Incognito link above
In main.html add an iframe,
<iframe id='testFrame' name='testFrame' onload='setUniqueSource(this)' src='' style="width:0; height:0; visibility:hidden;"></iframe>
, and some JavaScript code:
function checkResult() {
var a = frames[0].document.getElementById('test');
if (!a) return;
var color;
if (a.currentStyle) {
color = a.currentStyle.color;
} else {
color = frames[0].getComputedStyle(a, '').color;
}
var visited = (color == 'rgb(51, 102, 160)' || color == '#3366a0');
alert('mode is ' + (visited ? 'NOT Private' : 'Private'));
}
function setUniqueSource(frame) {
frame.src = "test.html?" + Math.random();
frame.onload = '';
}
Then in test.html that are loaded into the iFrame:
<style>
a:link { color: #336699; }
a:visited { color: #3366A0; }
</style>
<script>
setTimeout(function() {
var a = document.createElement('a');
a.href = location;
a.id = 'test';
document.body.appendChild(a);
parent.checkResult();
}, 100);
</script>
NOTE: trying this from the filesystem can make Chrome cry about "Unsafe Javascript". It
will, however, work serving from a webserver.
You can, in JavaScript, see JHurrah's answer. Except for not highlighting links, all incognito mode does is not save browse history and cookies. From google help page:
Webpages that you open and files downloaded while you are incognito
aren't recorded in your browsing and
download histories.
All new cookies are deleted after you close all incognito windows
that you've opened.
As you can see the differences between normal browsing and incognito happen after you visit the webpage, hence there is nothing that browser communicates to the server when it's in this mode.
You can see what exactly your browser sends to the server using one of many HTTP request analysers, like this one here. Compare the headers between normal session and incognito and you will see no difference.
If you are developing an Extension then you can use the tabs API to determine if a window/tab incognito.
More information can be found here.
If you are just working with a webpage, it is not easy, and it is designed to be that way. However, I have noticed that all attempts to open a database (window.database) fail when in incongnito, this is because when in incognito no trace of data is allowed to be left on the users machine.
I haven't tested it but I suspect all calls to localStorage fail too.
For those looking for a solution, here's a brief rundown of the current methods of detecting Private Browsing modes in various browsers as of October 2021:
Chromium: Similar to Vinnie James's answer, call navigator.storage.estimate(), grab the quota property and compare it to performance.memory.jsHeapSizeLimit. If the quota property is less than jsHeapSizeLimit, it's incognito. If jsHeapSizeLimit is undefined, use 1073741824 (1 GiB).
Safari for macOS: Use safari.pushNotification.requestPermission on a non-existent push server & grab the error. If "gesture" does not appear in the error, it's in private mode.
Safari for iOS: Create an iframe & add an error event listener using contentWindow.applicationCache on the iframe. If the error trips, it's in private mode.
Firefox: navigator.serviceWorker will be undefined in a private window.
Internet Explorer: window.indexedDB will be undefined in InPrivate mode.
You can see an implementation of these methods in the detectIncognito script I have available on GitHub.
Update This seems to not be working anymore
This uses a promise to wait for the asynchronous code to set a flag, so we can use it synchronously afterward.
let isIncognito = await new Promise((resolve, reject)=>{
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) reject('Check incognito failed');
else fs(window.TEMPORARY, 100, ()=>resolve(false), ()=>resolve(true));
});
then we can do
if(isIncognito) alert('in incognito');
else alert('not in incognito');
Note, to use await you need to be inside an async function. If you're not, you can wrap all your code inside one to be able to
Quick function based on Alok's Answer (note: this is asynchronous)
Update - not working anymore
function ifIncognito(incog,func){
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) console.log("checking incognito failed");
else {
if(incog) fs(window.TEMPORARY, 100, ()=>{}, func);
else fs(window.TEMPORARY, 100, func, ()=>{});
}
}
usage:
ifIncognito(true, ()=>{ alert('in incognito') });
// or
ifIncognito(false, ()=>{ alert('not in incognito') });
Here is the suggested answer written in ES6 syntaxt and slightly cleand up.
const isIncognito = () => new Promise((resolve, reject) => {
const fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
reject('Cant determine whether browser is running in incognito mode!');
}
fs(window.TEMPORARY, 100, resolve.bind(null, false), resolve.bind(null, true));
});
// Usage
isIncognito()
.then(console.log)
.catch(console.error)
Other answers seem to be no longer valid in recent chrome versions.
The idea is to find out storage estimates to determine if the tab is incognito or not. Storage size is less for incognito tabs.
Run this code in both normal and incognito window and note down the quota size.
const {quota} = await navigator.storage.estimate();
console.log(quota);
use quota size difference to implement the logic for incognito mode detection.
below logic works for Chrome v105:
const { quota } = await navigator.storage.estimate();
if (quota.toString().length === 10) {
console.log("gotcha: this is incognito tab"); //quota = 1102885027
} else {
console.log("this is a normal tab"); //quota = 296630877388
}
Also, look at this solution for much wider support (includes other browsers as well)
detectIncognito.ts
demo: https://detectincognito.com/
This works in May 2021: https://jsfiddle.net/2b1dk8oa/
The script has to be executed in a webpage, which is in an iframe.
try{
var ls = localStorage;
alert("You are not in Incognito Mode.");
}
catch(e) { alert("You are in Incognito Mode."); }

Is there a PhantomJs alternative with css 3d support

I'm trying to record a webpage using NodeJs. I am using PhantomJs to take screenshots of the page and ffmpeg to conver them to video. The problem is that the page I'm using uses 3d transform css, and PhantomJs does not support 3d transforms (http://phantomjs.org/supported-web-standards.html) and everything seems static.
Is there any alternative to PhantomJs that supports 3d transforms? Or maybe a different approach?
It's not necessary to be NodeJs, other languages like Python works too.
Here's the code I'm using right now:
var page = require("webpage").create();
page.viewportSize = { width: 500, height: 860 };
page.open("pageurl", function() {
// Initial frame
var frame = 0;
// Add an interval every 25th second
setInterval(function() {
// Render an image with the frame name
page.render("frames/dragon" + frame++ + ".png", { format: "png" });
// Exit after 50 images
if (frame > 100) {
phantom.exit();
}
}, 25);
});
Phantom JS is no longer being maintained so I would suggest using something like puppeteer which uses headless chrome and gives you the ability to do what you're requesting.
OBS supports this by way of Chromium Embedded Framework. There is an API for OBS, or you can use CEF directly.
An alternative method that I use is the Tab Capture API, by way of browser extension.
Have you tried using puppeteer. It uses chrome and its super fast
They have a simple example code in their readme file
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
Run this code here: https://try-puppeteer.appspot.com/
Also find more information about the screenshot command in the docs https://github.com/GoogleChrome/puppeteer/blob/v1.15.0/docs/api.md#pagescreenshotoptions
Good luck!

Capture screen shot of lazy loaded page with Node.js

I'm looking for a way to take a screenshot of a long web page every time it changes. I would like to use Node.js for this. My question is about how to render the full page with images and save it to disk ad an image file.
Most images on the webpage is lazy loaded. So I guess that I need to scroll down the entire page first, before taking a screen shot.
I tried different tools:
casperjs
node-webshot
phantomjs
All of them seems way too complicated, if not impossible, to even install. I didn't succeed with any of them.
casperjs seems like a really nice choice, but I can't get it to work within node.js. It keeps complaining, that casper.start() is not a valid method...
I got closest with node-webshot, but I did not manage to scroll down page.
This is my code so far:
var webshot = require('webshot');
var options = {
shotSize: {
height: 'all',
streamType: 'jpg'
}
};
webshot('www.xx.com', 'xx.com.jpg', options, function(err) {
// screen shot saved to 'xx.com.jpg'
});
BTW I'm developing on a mac. The finished Node app will be on a linux server.
Any comments or experiences are appreciated!
Can't really help with installing CasperJS since on Windows it works by simply using npm install casperjs -g.
I've put up a simple script to do screenshots:
var casper = require('casper').create();
casper.options.viewportSize = {width: 1600, height: 950};
var wait_duration = 5000;
var url = 'http://stackoverflow.com/questions/33803790/capture-screen-shot-of-lazy-loaded-page-with-node-js';
console.log("Starting");
casper.start(url, function() {
this.echo("Page loaded");
});
casper.then(function() {
this.scrollToBottom();
casper.wait(wait_duration, function() {
casper.capture('screen.jpg');
this.echo("Screen captured");
});
});
casper.then(function() {
this.echo("Exiting");
this.exit();
});
casper.run();
The code is fairly straightforward:
Load the url
Scroll to the bottom
Wait for a specific duration (wait_duration) for stuff to load
Do a screenshot
End
Hopefully, that works for you!
this code work for me with node in OSX, save it like test.js and run node test.js in CLI
var webshot = require('webshot');
var options = {
streamType: 'png',
windowSize: {
width: 1024,
height: 768
},
shotSize: {
width: 'all',
height: 'all'
}
};
webshot("blablabla.com","bla-image.png",options,(err) => {
if(err){
return console.log(err);
}
console.log('image succesfully');
});
you can automate it via Selenium, http://webdriver.io/. Yes, it's most like a testing engine, not a screen shot application, but you can fully control the browser automation and see the browser on your display while debugging
Start selenium server, with, for example, Google Chrome
Load your page
Do scrolling, clicking, everything with webdriver.io
Take a picture when you think it's a good time
close session
fast way to install selenium with nodejs -> https://github.com/vvo/selenium-standalone

Determine an installed app using Safari on iPhone

I would like to determine an installed app using custom URL scheme on iPhone Safari.
You may believe it is impossible to do this, but JavaScript helped me to figure this out.
<script>(function(){
var fallbackLink = '<?=$info['failed_url']?>'+window.location.search+window.location.hash;
var isiOS = navigator.userAgent.match('iPad') || navigator.userAgent.match('iPhone'),
isAndroid = navigator.userAgent.match('Android');
if (isiOS || isAndroid) {
document.getElementById('loader').src = '<?=$info['scheme']?>://'+window.location.search+window.location.hash;
fallbackLink = isAndroid ? '<?=$info['failed_url']?>' :
'<?=$info['failed_url']?>' ;
}
window.setTimeout(function (){ window.location.replace(fallbackLink); }, 1000);
})();</script>
here is my script.
I already know custom URL scheme of the iPhone application. It successfully launches the application if it exists on the iPhone. However, if the iPhone doesn't have the application, it redirects to a different page.
I put certain code on the failed web page to notice that user doesn't have the application. My plan was perfect until I found this.
The JavaScript redirection works even though the application is launched on iPhone after timeout.
Is there a way to stop JavaScript if iPhone launched application?
Thank you.
You can always cancel the timeout when the window loses focus.
var countdown = window.setTimeout(function (){
window.location.replace(fallbackLink);
}, 1000);
window.addEventListener("blur", function (){
window.clearTimeout(countdown);
}, false);

Checking JRE version inside browser

Basically, I'm wanting to figure out the best way to check the user's JRE version on a web page. I have a link to a JNLP file that I only want to display if the user's JRE version is 1.6 or greater. I've been playing around with the deployJava JavaScript code (http://java.sun.com/javase/6/docs/technotes/guides/jweb/deployment_advice.html) and have gotten it to work in every browser but Safari (by using deployJava.versionCheck). For whatever reason, Safari doesn't give the most updated JRE version number - I found this out by displaying the value of the getJREs() function. I have 1.6.0_20 installed, which is displayed in every other browser, but Safari keeps saying that only 1.5.0 is currently installed.
I've also tried using the createWebStartLaunchButtonEx() function and specifying '1.6.0' as the minimum version, but when I click the button nothing happens (in any browser).
Any suggestions?
FYI: Here's my code --
if (deployJava.versionCheck('1.6+')) {
var dir = location.href.substring(0,location.href.lastIndexOf('/')+1);
var url = dir + "tmaj.jnlp";
deployJava.createWebStartLaunchButton(url, '1.6.0');
} else {
var noticeText = document.createTextNode("In order to use TMAJ, you must visit the following link to download the latest version of Java:");
document.getElementById('jreNotice').appendChild(noticeText);
var link = document.createElement('a');
link.setAttribute('href', 'http://www.java.com/en/download/index.jsp');
var linkText = document.createTextNode("Download Latest Version of Java");
link.appendChild(linkText);
document.getElementById('jreDownloadLink').appendChild(link);
}
Probably the best bet would be to check the navigator.plugins array.
Here is a quick example that works in Chrome/Firefox. As far as I know, Internet Explorer does not provide access to the plugins array.
function getJavaVersion() {
var j, matches;
for (j = 0;j < navigator.plugins.length;j += 1) {
matches = navigator.plugins[j].description.match(/Java [^\d]+(\d+\.?\d*\.?\d*_?\d*)/i);
if (matches !== null) {
return matches[1];
}
}
return null;
};
console.log(getJavaVersion()); // => 1.6.0_16
Not sure if it helps you but you can specify the minimum jre version as a clause in the jnlp file. Webstart will not launch your app if the requirement is not met.
See the tag.
Also, have a look at
How to check JRE version prior to launch?

Categories