How to capture the screenshot of a specific element rather than entire page using Selenium Webdriver?
Asked Answered
C

25

96

Currently I'm trying to capture a screenshot using the Selenium WebDriver. But I can only obtain the whole page screen shot. However, what I wanted is just to capture a part of the page or perhaps just on specific element based on ID or any specific element locator. (For example, I wish to capture the picture with image id = "Butterfly")

Is there any way to capture a screenshot by selected item or element?

Copyboy answered 12/12, 2012 at 3:32 Comment(2)
AFAIK, the facility is only to capture the whole page. We do not have screenshot function that takes element id or name as input.Oraleeoralia
Anyone could tell me what is the method call for BUfferedImage in c#? I could not found any similar method related to this.Copyboy
W
134

We can get the element screenshot by cropping entire page screenshot as below:

driver.get("http://www.google.com");
WebElement ele = driver.findElement(By.id("hplogo"));

// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage  fullImg = ImageIO.read(screenshot);

// Get the location of element on the page
Point point = ele.getLocation();

// Get width and height of the element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();

// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(),
    eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);

// Copy the element screenshot to disk
File screenshotLocation = new File("C:\\images\\GoogleLogo_screenshot.png");
FileUtils.copyFile(screenshot, screenshotLocation);
Westering answered 12/12, 2012 at 7:9 Comment(21)
Thank you for reply. However, why my webdriver is different with your one. it use IWebDriver,ITakeScreenshot and there is no OutputType.FILE and BufferedImage... am i using the outdated version of webdriver selenium?Copyboy
Are you using C# webdriver binding?Westering
Yes,i think so. Previously i was using RC and i just change to use web driver lately.Copyboy
This implementation is for Java binding. This concept should work for C# also. But I am not much aware of C# language. You need to use C# equivalent libraries (BufferedImage, ImageIO...)Westering
Ohh i got it. Btw , thank you very much for providing me a such good example to refer.Copyboy
Anyone could tell me what is the method call for BUfferedImage in c#? I could not found any similar method related to this.Copyboy
Anyone has the solution for webdrivejs?Klinger
Does it matter if you use Point.getX() or just Point.x? I used the latter in my code, and it seems to work fine.Present
I sometimes run into exception like "RasterFormatException: (x + width) is outside Raster" for this type of implementation. But it doesn't happen all the time. I'm just using the element coordinates & size, so no way that can be wrong. Interestingly, no issue using other libraries like javaxt.com/javaxt-core/javaxt.io.ImagePresent
Thanks Surya, the above code is working in FF for me very well.Observant
The above code is not working in Chrome. An exception java.awt.image.RasterFormatException: (y + height) is outside of Raster was thrown at line BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(), eleWidth, eleHeight);Observant
Same kind of exception RasterFormatException in Chrome in some cases.Grammalogue
Well you may add a check if your value go outside of ranges.Externalism
@Externalism We can get to know range, which is cause of RasterFormatException. But, How can we control it ? If we adjust the range, than target element can not capture as defined.Dropping
Scroll the element into view before using this logic... Else scroll by a fixed range, say 500 pixels, check if element is in view. If yes, then trigger the above code. Don't forget to add the scrolled 500 pixels to the element height.Angelus
This won't work when the element has a negative coordinate (like when it's part of a drop-down list, for example).Largehearted
There are now 3 element-screenshot methods: screenshot_as_png, screenshot_as_base64, and screenshot. The answer by @rovr138 uses screenshot_as_png. If you just want to save to a file, element.screenshot(png_filename) should work.Subtropical
In Java, element screenshots can now be taken with the single method WebElement.getScreenshotAs(), which is analogous to the Python functions mentioned by Eponymous. However, it captured an incorrect area when I tried it with a zoomed page in Chrome (but worked fine without zooming). Conversely, Surya's answer can be adapted to work with a zoomed page. (It also would need to be adapted to work with a scrolled page and a page where the element is not fully on the page.)Hern
As @Hern said, please check my answer for a simplified version since you can now take a screenshot of a WebElement instance itself.Duarte
thank you @Westering to update your answer now it's element.Size.Width element.Location etc In C# !Teodoor
This isn't really a greatly suitable accepted answer any more as the W3C Webdriver spec defines a Take Element Screenshot command spec. Having the command operate closer to the browser and take the screenshot in a single stage reduces errors being introduced if the page is still rendering during the captureBevus
N
30

Here is a Python 3 version using Selenium webdriver and Pillow. This program captures the screenshot of the whole page and crop the element based on its location. The element image will be available as image.png. Firefox supports saving element image directly using element.screenshot_as_png('image_name').

from selenium import webdriver
from PIL import Image

driver = webdriver.Chrome()
driver.get('https://www.google.co.in')

element = driver.find_element_by_id("lst-ib")

location = element.location
size = element.size

driver.save_screenshot("shot.png")

x = location['x']
y = location['y']
w = size['width']
h = size['height']
width = x + w
height = y + h

im = Image.open('shot.png')
im = im.crop((int(x), int(y), int(width), int(height)))
im.save('image.png')

Update

Now chrome also supports individual element screenshots. So you may directly capture the screenshot of the web element as given below.

from selenium import webdriver
import io
from PIL import Image

driver = webdriver.Chrome()
driver.get('https://www.google.co.in')
image_binary = driver.find_element_by_id("lst-ib").screenshot_as_png 
img = Image.open(io.BytesIO(image_binary))
img.save("image.png")
Nanananak answered 25/7, 2018 at 11:19 Comment(6)
I'm pretty sure that element.size is given in points, whereas the screenshot produced by driver.save_screenshot has dimensions of pixels. If your screen has a pixel-to-point ratio other than 1 (e.g., retina MacBooks have two pixels per point -- a ratio of 2) then you need to multiply w and h by that ratio.Insectile
new version have been able to use element.screenshot('elemenent.png'), see the answer of @rovr138Embolectomy
@Embolectomy It was only available in Firefox when the answer was created. I think it is also available in chrome now. Updating the answer.Nanananak
I tried like this and gave me typeError. 'bytes' object is not callableKarlynkarma
@Karlynkarma For in memory loading do this. from StringIO import StringIO; from PIL import Image; img = Image.open(StringIO(image))Nanananak
I had a similar issue as @puppet. This is what worked for me: import io; from PIL import Image; img = Image.open(io.BytesIO(image)); img.save("image.png")Henning
R
11

The AShot framework from Yandex can be used for taking screenshots in Selenium WebDriver scripts for

  • full web pages
  • web elements

This framework can be found on https://github.com/yandex-qatools/ashot.

The code for taking the screenshots is very straightforward:

ENTIRE PAGE

Screenshot screenshot = new AShot()
        .shootingStrategy(new ViewportPastingStrategy(1000))
        .takeScreenshot(driver);

ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\results.png"));

SPECIFIC WEB ELEMENT

Screenshot screenshot = new AShot()
        .takeScreenshot(driver, driver.findElement(By.xpath("(//div[@id='ct_search'])[1]")));
    
ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\div_element.png"));

See more details and more code samples on this article.

Rodriguez answered 30/10, 2015 at 23:44 Comment(1)
Be careful you may also need .shootingStrategy(ShootingStrategies.viewportPasting(100)) too with SPECIFIC WEB ELEMENT mode, or it may not capture all element.Hawser
H
11

For everyone asking for code in C#, below is a simplified version of my implementation.

public static void TakeScreenshot(IWebDriver driver, IWebElement element)
{
    try
    {
        string fileName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".jpg";
        Byte[] byteArray = ((ITakesScreenshot)driver).GetScreenshot().AsByteArray;
        System.Drawing.Bitmap screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray));
        System.Drawing.Rectangle croppedImage = new System.Drawing.Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
        screenshot = screenshot.Clone(croppedImage, screenshot.PixelFormat);
        screenshot.Save(String.Format(@"C:\SeleniumScreenshots\" + fileName, System.Drawing.Imaging.ImageFormat.Jpeg));
    }
    catch (Exception e)
    {
        logger.Error(e.StackTrace + ' ' + e.Message);
    }
}
Headband answered 15/6, 2016 at 9:25 Comment(1)
Thank you. That was very helpful and was to the point and perfect.Ulick
K
10

In Node.js, I wrote the following code which works but it is not based on selenium's official WebDriverJS, but based on SauceLabs's WebDriver: WD.js and a very compact image library called EasyImage.

I just wanna emphasize that you cannot really take the screenshot of an element but what you should do is to first, take the screenshot of the whole page, then select the part of the page you like and crop that specific part:

browser.get(URL_TO_VISIT)
       .waitForElementById(dependentElementId, webdriver.asserters.isDisplayed, 3000)
       .elementById(elementID)
        .getSize().then(function(size) {
            browser.elementById(elementID)
                   .getLocation().then(function(location) {
                        browser.takeScreenshot().then(function(data) {
                            var base64Data = data.replace(/^data:image\/png;base64,/, "");
                            fs.writeFile(filePath, base64Data, 'base64', function(err) {
                                if (err) {
                                    console.log(err);
                                } 
                                else {
                                    cropInFile(size, location, filePath);
                                }
                                doneCallback();
                        });
                    });
                });
            }); 

And the cropInFileFunction, goes like this:

var cropInFile = function(size, location, srcFile) {
    easyimg.crop({
            src: srcFile,
            dst: srcFile,
            cropwidth: size.width,
            cropheight: size.height,
            x: location.x,
            y: location.y,
            gravity: 'North-West'
        },
        function(err, stdout, stderr) {
            if (err) throw err;
        });
};
Klinger answered 15/4, 2014 at 14:41 Comment(1)
Your EasyImage library is broken: "ImageMagickMissingError"Actomyosin
J
6

I wasted a lot of time on taking screenshot and I want to save yours. I have used chrome + selenium + c# the result was totally horrible. Finally i wrote a function :

driver.Manage().Window.Maximize();
             RemoteWebElement remElement = (RemoteWebElement)driver.FindElement(By.Id("submit-button")); 
             Point location = remElement.LocationOnScreenOnceScrolledIntoView;  

             int viewportWidth = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientWidth"));
             int viewportHeight = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientHeight"));

             driver.SwitchTo();

             int elementLocation_X = location.X;
             int elementLocation_Y = location.Y;

             IWebElement img = driver.FindElement(By.Id("submit-button"));

             int elementSize_Width = img.Size.Width;
             int elementSize_Height = img.Size.Height;

             Size s = new Size();
             s.Width = driver.Manage().Window.Size.Width;
             s.Height = driver.Manage().Window.Size.Height;

             Bitmap bitmap = new Bitmap(s.Width, s.Height);
             Graphics graphics = Graphics.FromImage(bitmap as Image);
             graphics.CopyFromScreen(0, 0, 0, 0, s);

             bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);

             RectangleF part = new RectangleF(elementLocation_X, elementLocation_Y + (s.Height - viewportHeight), elementSize_Width, elementSize_Height);

             Bitmap bmpobj = (Bitmap)Image.FromFile(filePath);
             Bitmap bn = bmpobj.Clone(part, bmpobj.PixelFormat);
             bn.Save(finalPictureFilePath, System.Drawing.Imaging.ImageFormat.Png); 
Jenifer answered 3/7, 2013 at 12:13 Comment(1)
It works perfectly fine as long as you try capturing an element which is visible without scrolling. When you need to scroll to an element to capture it, then the y offset is calculated from the top of the page, which then exceeds the boundaries of the full-screen image. So the easiest solution is to either increase the screen size code this.driver.manage().window().setSize(new Dimension(1680, 1050)); or to remove any non required elements via css. The proper solution would be to calculate the y-offset from scrolling.Took
V
6

Python 3

Tried with Selenium 3.141.0 and chromedriver 73.0.3683.68, this works,

from selenium import webdriver

chromedriver = '/usr/local/bin/chromedriver'
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('window-size=1366x768')
chromeOptions.add_argument('disable-extensions')
cdriver = webdriver.Chrome(options=chromeOptions, executable_path=chromedriver)

cdriver.get('url')
element = cdriver.find_element_by_css_selector('.some-css.selector')

element.screenshot_as_png('elemenent.png')

No need to get a full image and get a section of a fullscreen image.

This might not have been available when Rohit's answer was created.

Vendor answered 14/4, 2019 at 15:24 Comment(0)
L
5

Surya's answer works great if you don't mind involving disk IO. If you'd rather not, then this method may be better for you

private Image getScreenshot(final WebDriver d, final WebElement e) throws IOException {
    final BufferedImage img;
    final Point topleft;
    final Point bottomright;

    final byte[] screengrab;
    screengrab = ((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES);

    img = ImageIO.read(new ByteArrayInputStream(screengrab));

    //crop the image to focus on e
    //get dimensions (crop points)
    topleft = e.getLocation();
    bottomright = new Point(e.getSize().getWidth(),
                            e.getSize().getHeight());

    return img.getSubimage(topleft.getX(),
                           topleft.getY(),
                           bottomright.getX(),
                           bottomright.getY());
}

If you prefer you can skip declaring screengrab and instead doing

img = ImageIO.read(
    new ByteArrayInputStream(
        ((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES)));

which is cleaner, but I left it in for clarity. You can then save it as a file or put it in a JPanel to your heart's content.

Lighten answered 29/1, 2015 at 5:42 Comment(0)
D
5

I think most of the answers here are over-engineered. The way i did it is through 2 helper methods, the first to wait for an element based on any selector; and the second to take a screenshot of it.

Note: We cast the WebElement to a TakesScreenshot instance, so we only capture that element in the image specifically. If you want the full page/window, you should cast driver instead.

Edit: I forgot to say that i'm using Java and Selenium v3 (but should be the same for v4)

WebDriver driver = new FirefoxDriver(); // define this somewhere (or chrome etc)

public <T> T screenshotOf(By by, long timeout, OutputType<T> type) {
    return ((TakesScreenshot) waitForElement(by, timeout))
            .getScreenshotAs(type);
}

public WebElement waitForElement(By by, long timeout) {
    return new WebDriverWait(driver, timeout)
            .until(driver -> driver.findElement(by));
}

And then just screenshot whatever u want like this :

long timeout = 5;   // in seconds
/* Screenshot (to file) based on first occurence of tag */
File sc = screenshotOf(By.tagName("body"), timeout, OutputType.FILE); 
/* Screenshot (in memory) based on CSS selector (e.g. first image in body
who's "src" attribute starts with "https")  */
byte[] sc = screenshotOf(By.cssSelector("body > img[href^='https']"), timeout, OutputType.BYTES);
Duarte answered 1/1, 2021 at 10:35 Comment(0)
P
3

If you are looking for a JavaScript solution, here's my gist:

https://gist.github.com/sillicon/4abcd9079a7d29cbb53ebee547b55fba

const webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;
const fs = require("fs");

function takeScreenshot(driver, webElement, imagePath) { // driver -> webDriver; webElement -> WebElement; imagePath -> physical path to save the image 
    var base64Data = "";
    var location = {};
    var bulk = [];
    driver.then(_ => {
        webElement.getLocation().then(e => {
            location.x = e.x;
            location.y = e.y;
        });
        webElement.getSize().then(e => {
            location.height = e.height;
            location.width = e.width;
        });
        driver.manage().window().getSize().then(e => {
            location.browserHeight = e.height;
            location.broserWidth = e.width;
        });
    }).then(_ => {
        driver.takeScreenshot().then(data => {
            base64Data = data.replace(/^data:image\/png;base64,/, "");
        });
    }).then(_ => {
        const sizeLimit = 700000; // around 700kb
        const imgSize = base64Data.length;
        driver.executeScript(() => {
            window.temp = new Array;
        }).then(_ => {
            for (var i = 0; i < imgSize; i += sizeLimit) {
                bulk.push(base64Data.substring(i, i + sizeLimit));
            }
            bulk.forEach((element, index) => {
                driver.executeScript(() => {
                    window.temp[arguments[0]] = arguments[1];
                }, index, element);
            });
        });
    }).then(_ => {
        driver.executeScript(() => {
            var tempBase64 = window.temp.join("");
            var image = new Image();
            var location = arguments[0];
            image.src = "data:image/png;base64," + tempBase64;
            image.onload = function () {
                var canvas = document.createElement("canvas");
                canvas.height = location.height;
                canvas.width = location.width;
                canvas.style.height = location.height + 'px';
                canvas.style.width  = location.width + 'px';
                var ctx = canvas.getContext('2d');
                ctx.drawImage(image, -location.x, -location.y);
                window.canvasData = canvas.toDataURL();
                window.temp = [];
            }
        }, location);
    }).then(_ => {
        return driver.executeScript(() => {
            var data = window.canvasData;
            window.canvasData = "";
            return data;
        }).then(data => {
            var tempData = data.replace(/^data:image\/png;base64,/, "");
            fs.writeFileSync(imagePath, tempData, "base64");
            console.log("Image capture complete");
        });
    });
}

The basic idea is the same, take the screen shot first, then crop it. However, my solution will not require other libraries, just pure WebDriver API code. However, the side effect is that it may increase the load of your testing browser.

Pester answered 22/9, 2017 at 21:55 Comment(1)
Please paste the code in your answer instead of linking to another sourceButch
E
2
public void GenerateSnapshot(string url, string selector, string filePath)
    {
        using (IWebDriver driver = new ChromeDriver())
        {
            driver.Navigate().GoToUrl(url);
            var remElement = driver.FindElement(By.CssSelector(selector));
            Point location = remElement.Location;

            var screenshot = (driver as ChromeDriver).GetScreenshot();
            using (MemoryStream stream = new MemoryStream(screenshot.AsByteArray))
            {
                using (Bitmap bitmap = new Bitmap(stream))
                {
                    RectangleF part = new RectangleF(location.X, location.Y, remElement.Size.Width, remElement.Size.Height);
                    using (Bitmap bn = bitmap.Clone(part, bitmap.PixelFormat))
                    {
                        bn.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
                    }
                }
            }
            driver.Close();
        }
    }
Electrophorus answered 15/3, 2016 at 13:7 Comment(0)
D
2

Consider using needle - tool for automated visual comparison https://github.com/bfirsh/needle , which has built-in functionality that allows to take screenshots of specific elements (selected by CSS selector). The tool works on Selenium's WebDriver and it's written in Python.

Disaster answered 1/3, 2017 at 15:1 Comment(0)
B
2

Here is an extension function for C#:

public static BitmapImage GetElementImage(this IWebDriver webDriver, By by)
{
    var elements = webDriver.FindElements(by);
    if (elements.Count == 0)
        return null;

    var element = elements[0];
    var screenShot = (webDriver as ITakesScreenshot).GetScreenshot();
    using (var ms = new MemoryStream(screenShot.AsByteArray))
    {
        Bitmap screenBitmap;
        screenBitmap = new Bitmap(ms);
        return screenBitmap.Clone(
            new Rectangle(
                element.Location.X,
                element.Location.Y,
                element.Size.Width,
                element.Size.Height
            ),
            screenBitmap.PixelFormat
        ).ToBitmapImage();
    }
}

Now you can use it to take the image of any element like this:

var image = webDriver.GetElementImage(By.Id("someId"));
Braddy answered 26/10, 2017 at 8:20 Comment(0)
K
1

Below the function for taking snapshot a specific element in Selenium. Here the driver is a type of WebDriver.

private static void getScreenshot(final WebElement e, String fileName) throws IOException {
  final BufferedImage img;
  final Point topleft;
  final Point bottomright;
  final byte[] screengrab;
  screengrab = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
  img = ImageIO.read(new ByteArrayInputStream(screengrab));
  topleft = e.getLocation();
  bottomright = new Point(e.getSize().getWidth(), e.getSize().getHeight());
  BufferedImage imgScreenshot= 
      (BufferedImage)img.getSubimage(topleft.getX(), topleft.getY(), bottomright.getX(), bottomright.getY());
  File screenshotLocation = new File("Images/"+fileName +".png");    
  ImageIO.write(imgScreenshot, "png", screenshotLocation);
 }
Katherinakatherine answered 2/7, 2017 at 6:56 Comment(1)
See this link for more: [Automation Hub Point] (automationhubpoint.blogspot.in/2017/01/…)Katherinakatherine
R
1

c# code:

public Bitmap MakeElemScreenshot( IWebDriver driver, WebElement elem)
{
    Screenshot myScreenShot = ((ITakesScreenshot)driver).GetScreenshot();

    Bitmap screen = new Bitmap(new MemoryStream(myScreenShot.AsByteArray));
    Bitmap elemScreenshot = screen.Clone(new Rectangle(elem.Location, elem.Size), screen.PixelFormat);

    screen.Dispose();

    return elemScreenshot;
}
Retrieval answered 31/1, 2019 at 11:59 Comment(0)
S
0
using System.Drawing;
using System.Drawing.Imaging;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

public void ScreenshotByElement()
{
    IWebDriver driver = new FirefoxDriver();
    String baseURL = "www.google.com/"; //url link
    String filePath = @"c:\\img1.png";      

    driver.Navigate().GoToUrl(baseURL);
    var remElement = driver.FindElement(By.Id("Butterfly"));
    Point location = remElement.Location;

    var screenshot = (driver as FirefoxDriver).GetScreenshot();
    using (MemoryStream stream = new MemoryStream(screenshot.AsByteArray))
    {
        using (Bitmap bitmap = new Bitmap(stream))
        {
            RectangleF part = new RectangleF(location.X, location.Y, remElement.Size.Width, remElement.Size.Height);
            using (Bitmap bn = bitmap.Clone(part, bitmap.PixelFormat))
            {
                bn.Save(filePath, ImageFormat.Png);                        
            }
        }
    }
}
Shuma answered 8/12, 2016 at 2:45 Comment(0)
T
0

If you get an exception java.awt.image.RasterFormatException in chrome, or you want to scroll a element into view then capture a screenshot.

Here is a solution from @Surya answer.

        JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
        Long offsetTop = (Long) jsExecutor.executeScript("window.scroll(0, document.querySelector(\""+cssSelector+"\").offsetTop - 0); return document.querySelector(\""+cssSelector+"\").getBoundingClientRect().top;");

        WebElement ele = driver.findElement(By.cssSelector(cssSelector));

        // Get entire page screenshot
        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        BufferedImage  fullImg = ImageIO.read(screenshot);

        // Get the location of element on the page
        Point point = ele.getLocation();

        // Get width and height of the element
        int eleWidth = ele.getSize().getWidth();
        int eleHeight = ele.getSize().getHeight();

        // Crop the entire page screenshot to get only element screenshot
        BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), Math.toIntExact(offsetTop),
                eleWidth, eleHeight);
        ImageIO.write(eleScreenshot, "png", screenshot);

        // Copy the element screenshot to disk
        File screenshotLocation = new File("c:\\temp\\div_element_1.png");
        FileUtils.copyFile(screenshot, screenshotLocation);
Trichromat answered 26/11, 2018 at 12:52 Comment(1)
I am using selenium-java-2.53.1, compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.53.1', chrome-web-driver, i am trying to crop By.xpath(".//img[@class = 'captcha']") from the webpage resident.uidai.gov.in/offlineaadhaar, But your code is not working proper. Its cropping some wrong portion of the page. can you please help me for getting the captcha cropped.Sokoto
C
0

This is my version, in C#, I was basically get most part from Brook's answer and modified it to fit my purpose

public static byte[] GetElementImage(this IWebElement element)
    {
        var screenShot = MobileDriver.Driver.GetScreenshot();
        using (var stream = new MemoryStream(screenShot.AsByteArray))
        {
            var screenBitmap = new Bitmap(stream);
            var elementBitmap = screenBitmap.Clone(
                new Rectangle(
                    element.Location.X,
                    element.Location.Y,
                    element.Size.Width,
                    element.Size.Height
                ),
                screenBitmap.PixelFormat
            );
            var converter = new ImageConverter();
            return (byte[]) converter.ConvertTo(elementBitmap, typeof(byte[]));
        }
    }
Cementum answered 3/3, 2020 at 19:40 Comment(0)
R
0

To take a screenshot for a specific element you can now just use this:

public void takeCanvasScreenshot(WebElement element, String imageName) {
   
   File screenshot = element.getScreenshotAs(OutputType.FILE);

   try {
       FileUtils.copyFile(screenshot, new File("src/main/resources/screenshots/" + imageName + ".png"));
   } catch (IOException e) {
       e.printStackTrace();
   }
}
Rudy answered 28/4, 2021 at 12:37 Comment(0)
T
0

For C#, below code can work .

try  
{
  
IWebElement transactions = driver.FindElement(By.XPath(".//*[@id='some element']"));

Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();

string title = "some title";

screenshot.SaveAsFile(title, ScreenshotImageFormat.Jpeg);
                    
}
catch (Exception)
{

// handle if element not found 

}
Triton answered 20/7, 2021 at 6:57 Comment(0)
F
0

In Python using Selenium with Chrome driver,

This is how simply you can take a screenshot of a specific element (let's say the element with an ID).

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('URL')

element = driver.find_element(By.ID, "mention the id here")
element.screenshot('image.png')
Flavorous answered 24/6, 2023 at 10:55 Comment(0)
L
0
ele.screenshot('image.jpg') # use selenium 
#or 
urlretrieve(url=bg_image_url, filename='image.jpg') # from urllib.request import urlretrieve
Lecherous answered 24/11, 2023 at 20:11 Comment(0)
A
-1

I'm using a modified version of @Brook's answer and is working fine even for elements that needs the page to be scrolled.

public void TakeScreenshot(string fileNameWithoutExtension, IWebElement element)
{
    // Scroll to the element if necessary
    var actions = new Actions(_driver);
    actions.MoveToElement(element);
    actions.Perform();
    // Get the element position (scroll-aware)
    var locationWhenScrolled = ((RemoteWebElement) element).LocationOnScreenOnceScrolledIntoView;
    var fileName = fileNameWithoutExtension + ".png";
    var byteArray = ((ITakesScreenshot) _driver).GetScreenshot().AsByteArray;
    using (var screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray)))
    {
        var location = locationWhenScrolled;
        // Fix location if necessary to avoid OutOfMemory Exception
        if (location.X + element.Size.Width > screenshot.Width)
        {
            location.X = screenshot.Width - element.Size.Width;
        }
        if (location.Y + element.Size.Height > screenshot.Height)
        {
            location.Y = screenshot.Height - element.Size.Height;
        }
        // Crop the screenshot
        var croppedImage = new System.Drawing.Rectangle(location.X, location.Y, element.Size.Width, element.Size.Height);
        using (var clone = screenshot.Clone(croppedImage, screenshot.PixelFormat))
        {
            clone.Save(fileName, ImageFormat.Png);
        }
    }
}

The two ifs were necessary (at least for the chrome driver) because the size of the crop exceeded in 1 pixel the screenshot size, when scrolling was needed.

Ablaut answered 2/12, 2016 at 0:34 Comment(3)
I get this error when I try your method: Unable to cast transparent proxy to type 'OpenQA.Selenium.Remote.RemoteWebElement'Bellwort
I use this exclusively with Chrome Driver, which driver do you use?Ablaut
I am also using ChromeDriver. My tests are using IWebElements and we're following the PageFactory method from the OpenQA.Selenium.Support nuget package.Bellwort
Q
-1

I believe this isn't going to work for you as you use C# and my solution includes a Java library, however maybe others will find it helpful.

For capturing custom screenshots you can use the Shutterbug library. The specific call for this purpose would be:

Shutterbug.shootElement(driver, element).save();
Quintuplet answered 13/1, 2017 at 8:45 Comment(0)
W
-1

I followed the sample code from @codeslord, but for some reason I had to access my screenshot data differently:

 # Open the Firefox webdriver
 driver = webdriver.Firefox()
 # Find the element that you're interested in
 imagepanel = driver.find_element_by_class_name("panel-height-helper")
 # Access the data bytes for the web element
 datatowrite = imagepanel.screenshot_as_png
 # Write the byte data to a file
 outfile = open("imagepanel.png", "wb")
 outfile.write(datatowrite)
 outfile.close()

(using Python 3.7, Selenium 3.141.0 and Mozilla Geckodriver 71.0.0.7222)

Wind answered 4/2, 2020 at 18:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.