<p dir="auto">from discussions in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="179690302" data-permission-text="Title is private" data-url="https://github.com/electron/electron/issues/7378" data-hovercard-type="issue" data-hovercard-url="/electron/electron/issues/7378/hovercard" href="https://github.com/electron/electron/issues/7378">#7378</a></p>
<ul dir="auto">
<li>Electron version: 1.0.2</li>
<li>Operating system: 10.12</li>
</ul>
<p dir="auto">I tried <code class="notranslate">webContents.capturePage</code>, but it can only capture the "visible" part of the page. If the height of your html node is larger than the BrowserWindow (or when there's a scroll bar), the overflow part is not included in the captured image. Is there any way to capture the whole page?</p>
<h3 dir="auto">Expected behavior</h3>
<p dir="auto"><code class="notranslate">webContents.capturePage</code> take a snapshot of the whole complete webpage</p>
<h3 dir="auto">Actual behavior</h3>
<p dir="auto">only visible part is captured.</p>
<h3 dir="auto">How to reproduce</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="            const remote = require('electron').remote;
            const webContents = remote.getCurrentWebContents();

            webContents.capturePage({
                x: 0,
                y: 0,
                width: 1000,
                height: 2000
            }, (img) =&gt; {
                remote.require('fs')
                    .writeFile(TEMP_URL, img.toPng());
            });"><pre class="notranslate">            <span class="pl-k">const</span> <span class="pl-s1">remote</span> <span class="pl-c1">=</span> <span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'electron'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">remote</span><span class="pl-kos">;</span>
            <span class="pl-k">const</span> <span class="pl-s1">webContents</span> <span class="pl-c1">=</span> <span class="pl-s1">remote</span><span class="pl-kos">.</span><span class="pl-en">getCurrentWebContents</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

            <span class="pl-s1">webContents</span><span class="pl-kos">.</span><span class="pl-en">capturePage</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
                <span class="pl-c1">x</span>: <span class="pl-c1">0</span><span class="pl-kos">,</span>
                <span class="pl-c1">y</span>: <span class="pl-c1">0</span><span class="pl-kos">,</span>
                <span class="pl-c1">width</span>: <span class="pl-c1">1000</span><span class="pl-kos">,</span>
                <span class="pl-c1">height</span>: <span class="pl-c1">2000</span>
            <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">img</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
                <span class="pl-s1">remote</span><span class="pl-kos">.</span><span class="pl-en">require</span><span class="pl-kos">(</span><span class="pl-s">'fs'</span><span class="pl-kos">)</span>
                    <span class="pl-kos">.</span><span class="pl-en">writeFile</span><span class="pl-kos">(</span><span class="pl-c1">TEMP_URL</span><span class="pl-kos">,</span> <span class="pl-s1">img</span><span class="pl-kos">.</span><span class="pl-en">toPng</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<ul dir="auto">
<li>Electron version: 1.4.13</li>
<li>Operating system: MacOS 10.12.2 running on MacBook Pro (Retina, 13-inch, Early 2015)</li>
</ul>
<h3 dir="auto">Expected behavior</h3>
<p dir="auto">webview.capturePage() without specifying a dimension should return an image with the full viewable area on a Retina display. The dimensions of the resulting image should be either the actual pixels of the viewable area or perhaps the actual pixels * the device scale factor.</p>
<p dir="auto">Specifying a dimension should return the viewable area of that dimension with the resulting image being sized correctly (and consistently with the use case of no rect specified).</p>
<h3 dir="auto">Actual behavior</h3>
<p dir="auto">Calling webview.capturePage() without specifying a dimension returns in image that is the pixel size of the viewable area * the scale factor the area covered by the viewable area divided by the scale factor.</p>
<p dir="auto">For example, on a webview that is 524 pixels wide, the resulting image of capturePage() is 1048 pixels wide, but only contains the image data from the first 262 pixels. That image is then upsized by the scale factor twice to get to the 1048 width. Not only does this not capture the full viewable page, it also introduces significant scaling artifacts.</p>
<p dir="auto">Similar results occur if a rect is specified to capturePage.</p>
<h3 dir="auto">How to reproduce</h3>
<p dir="auto">On a Retina display, create a page with a webview that loads some web site:<br>
<code class="notranslate">&lt;webview id="webview" src="http://www.msn.com/" &gt;&lt;/webview&gt;</code></p>
<p dir="auto">Capture the page:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="// used to get the viewable dimensions of the webview
function getWebviewMeta(cb) {
    var code = &quot;var r = {}; \
        r.totalHeight = document.body.offsetHeight; \
        r.pageHeight = window.innerHeight; \
        r.pageWidth = window.innerWidth; \
        r;&quot;;
    webview.executeJavaScript(code, false, function(r) {
        let webviewMeta = {};
        webviewMeta.captureHeight = r.pageHeight;
        webviewMeta.captureWidth = r.pageWidth;
        cb(webviewMeta);
    });
}

getWebviewMeta(function(webviewMeta) {
    let captureRect = {
        x: 0, y: 0,
        width: webviewMeta.captureWidth,
        height: webviewMeta.captureHeight
    };

    webview.capturePage((img) =&gt; {
        console.log(&quot;image size: &quot;, img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testDefault.jpg, I used jetpack.writeAsync
    });

    webview.capturePage(captureRect, (img) =&gt; {
        console.log(&quot;image size: &quot;, img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testSetViewSize.jpg, I used jetpack.writeAsync
    });

    captureRect.width = +captureRect.width * electron.screen.getPrimaryDisplay().scaleFactor;
    captureRect.height = +captureRect.height * electron.screen.getPrimaryDisplay().scaleFactor;

    webview.capturePage(captureRect, (img) =&gt; {
        console.log(&quot;image size: &quot;, img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testScaled.jpg, I used jetpack.writeAsync
    });
});"><pre class="notranslate"><code class="notranslate">// used to get the viewable dimensions of the webview
function getWebviewMeta(cb) {
    var code = "var r = {}; \
        r.totalHeight = document.body.offsetHeight; \
        r.pageHeight = window.innerHeight; \
        r.pageWidth = window.innerWidth; \
        r;";
    webview.executeJavaScript(code, false, function(r) {
        let webviewMeta = {};
        webviewMeta.captureHeight = r.pageHeight;
        webviewMeta.captureWidth = r.pageWidth;
        cb(webviewMeta);
    });
}

getWebviewMeta(function(webviewMeta) {
    let captureRect = {
        x: 0, y: 0,
        width: webviewMeta.captureWidth,
        height: webviewMeta.captureHeight
    };

    webview.capturePage((img) =&gt; {
        console.log("image size: ", img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testDefault.jpg, I used jetpack.writeAsync
    });

    webview.capturePage(captureRect, (img) =&gt; {
        console.log("image size: ", img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testSetViewSize.jpg, I used jetpack.writeAsync
    });

    captureRect.width = +captureRect.width * electron.screen.getPrimaryDisplay().scaleFactor;
    captureRect.height = +captureRect.height * electron.screen.getPrimaryDisplay().scaleFactor;

    webview.capturePage(captureRect, (img) =&gt; {
        console.log("image size: ", img.getSize());
        let jpgFile = img.toJPEG(90);
        // save file as testScaled.jpg, I used jetpack.writeAsync
    });
});
</code></pre></div>
<p dir="auto">The first two results, testDefault.jpg and testSetViewSize.jpg will be identical. They will be captureRect * scale factor in size but will only contain captureRect / scale factor from the webview.</p>
<p dir="auto">The third result, testScaled.jpg, will contain the captureRect data from the webview but will be captureRect * scale factor * scale factor in size.</p>
<p dir="auto">All images have upscaling artifacts in them.</p>
<h3 dir="auto">Note</h3>
<p dir="auto">On non-retina displays (where the scale factor is 1), capturePage works as expected.</p>
<p dir="auto">Also, using webview.capturePage or webview.getWebContents().capturePage makes no difference. It also does not matter if the code is executed in the main or renderer process. I wouldn't expect there to be a difference in either, but I did test both to make sure.</p>
<p dir="auto">I have a discussion started about this but decided to enter an issue here because I believe there is a bug in how the scale factor is used. <a href="https://discuss.atom.io/t/webview-capturepage-doesnt-capture-full-page-on-retina-display/37560" rel="nofollow">https://discuss.atom.io/t/webview-capturepage-doesnt-capture-full-page-on-retina-display/37560</a></p>