FindBy strategies for Selenium explained

The @FindBy annotation is used in Page Objects in Selenium tests to specify the object location strategy for a WebElement or a list of WebElements. Using the PageFactory, these WebElements are usually initialized when a Page Object is created. In this post, I will demonstrate various ways in which you can use @FindBy annotations to efficiently locate (groups of) WebElements.

The @FindBy annotation is used to locate one or more WebElements using a single criterion. For example, to identify all elements that have the same class attribute, we could use the following identification:

@FindBy(how = How.CLASS_NAME, using = "classname")
private List<WebElement> singlecriterion;

If we are sure there is only a single element that is identified by our location strategy, for example when we use the element ID, we can also directly assign the result to a WebElement variable:

@FindBy(how = How.ID, using = "elementid")
private WebElement element;

To instantiate the elements, we call the initElements method of the PageFactory class:

PageFactory.initElements(driver, this);

@FindBys and @FindAll
In some cases we want (or need) to use more than a single criterion to identify one or more objects, for instance when page elements do not have a unique ID. In this case, there are two possible annotations that can be used:

  • The @FindBys annotation is used in case elements need to match all of the given criteria
  • The @FindAll annotation is used in case elements need to match at least one of the given criteria

Let’s take a look at an example that illustrates the difference between the two.

The Parabank homepage contains two textboxes, one for the username and one for the password. Both elements have a name attribute that we are going to use to identify them within a Page Object.

Using @FindBys:

	@FindBy(how = How.NAME, using = "username"),
	@FindBy(how = How.NAME, using = "password")
private List<WebElement> bothcriteria;

The bothcriteria list should contain 0 elements, as there is no element that has both a name attribute with the value username and a name attribute with the value password.

Using @FindAll:

	@FindBy(how = How.NAME, using = "username"),
	@FindBy(how = How.NAME, using = "password")
private List<WebElement> eithercriterion;

The eithercriterion list should contain 2 elements, as there is one element that has a name attribute with the value username and also one that has a name attribute with the value password.

For validation purposes, if we print the number of results found by all of the above strategies using

System.out.println("Using @FindBy, we found " + singlecriterion.size() + " element(s)");
System.out.println("Using @FindBys, we found " + bothcriteria.size() + " element(s)");
System.out.println("Using @FindAll, we found " + eithercriterion.size() + " element(s)");

we see this:
Results for different FindBy strategiesIt clearly works exactly as expected!

A more verbose FindBy
Finally, if you have a lot of elements within your Page Object, you can also use a more verbose way of specifying your @FindBy strategy. For example

@FindBy(className = "classname")

gives the exact same results as

@FindBy(how = How.CLASS_NAME, using = "classname")

79 thoughts on “FindBy strategies for Selenium explained

  1. Nice job Bas, as always…very useful tutorial and great topic…this is a really efficient way to work with page elements…saves a lot of keystrokes and makes the code much easier to read.

  2. Hi Sunny,

    a NoSuchElementException is still thrown if you use for example

    @FindBy(how = How.CLASS_NAME, using = “classname”)
    private WebElement element;

    and your element does not exist on the page.

    If you use

    @FindBy(how = How.CLASS_NAME, using = “classname”)
    private List elementlist;

    you will always have a list of WebElements you need to loop through. If you specify your How’s incorrectly you might end up with an empty List, which might also result in NoSuchElementExceptions or NullPointerExceptions depending on your implementation.

    So by no means is using @FindBy a way to prevent NoSuchElementExceptions from occurring.

  3. Hi Bas,

    I am using Selenium C# code to create my test scripts.

    At once place I need to add mileage in required input filed. Through selenium code I enter the mileage and click on Next link.

    When my Firefox browser is opened it works fine it takes mileage input and click on next link and it slides to next screen.

    But when my Firefox browser is minimized it does not work, it takes input even though while clicking on Next it gives error to enter mileage.

    wait.Until(ExpectedConditions.ElementToBeClickable(By.Id(“mileageInput”))).SendKeys(“99”); Log.Info(“Mileage input end” + _driver.FindElement(By.Id(“mileageInput”)).Text);

    Also note that in log file input data is displayed correctly though while clicking next it gives error.

      • Thanks Bas!

        I appreciate your efforts to help people like us!

        Using my test script, I am creating bulk data by providing bulk input through .csv.

        So while my test script is executing I am doing another work and wanted it to be executed. If I did not minimize the browser just work with any other application then also it is not working. Script runs only in the case the browser is focused.

        Let me know in future you come across any solution for this.

        • Hi Manasi,

          I get your problem. Are there no ways to work around this? For example:

          * by using a different workstation to run your data entry script / test on?
          * by bypassing the UI altogether and entering the data using an API or a database insert?

          • Hi Bas,

            Here, I am with a new issue.

            I have a test script written in Selenium C# and working properly in FireFox.

            Now I am trying to execute the script in chrome. But when I pass 17 characters of input through sendKeys() method but in input field only few characters are input others are missing.

            It would be great if you can help me in this.

            Facing the same issue mentioned in

            And tried the solutions mentioned in this like sending single key one by one but didn’t work.

            Please suggest.

          • Hi Manasi,

            did you try to change your keyboard language too like it is suggested in the link you provided?

            If that didn’t help either I’m afraid I don’t know a solution to your issue either..

  4. Hi Bas,
    I tried to use:
    [FindsBy(How = How.XPath, Using = “//*[@id=’sidebar’]/div[2]/div/div/div”)]
    public List allElements;

    I am getting following ERROR:
    ‘system.argumentexception: object of type ‘castle.Proxies.IwrapsElementProxy_1’ cannot be converted to type ‘System.Collections.Generic.List 1 [OpenQA.Selenim.IWebElemen]’

    Any help is much appreciated.


    • Could you send me the code for the class where this is occurring, to bas AT ? I don’t think this is a really difficult one (just a matter of using the wrong object type in your code) but I can’t say without taking a look at the class as a whole. Please also specify in the mail if there are any other NuGet packages I need apart from Selenium and Castle DynamicProxy (which I think you’re using here).

  5. I created the selenium test project using microsoft test framework with c#.
    In PageFactory pattern how we can manage the element not found exception as one of my page is loaded with static content and some filed populated with web api call, so problem is until that filed populated my test case throwing the error element not visible or element not found exception

    Kindly provide the C# example with pagefactory pattern

    • Hi Swapnil,

      when you use the PageFactory pattern the element is retrieved from the DOM (using FindElement()) every time you reference it. The problem is that it isn’t there when you reference it, because your page content is dynamic. This is one of the problems I have with PageFactory too, and it’s also the reason I do not use it. Instead, what I have done is implementing a wrapper method that waits for a specific time interval every time an object is referenced, before throwing an error. See this post for an example.

      I’m aware that this isn’t a direct answer to your question but it is the best I can do at the moment.

  6. Pingback: Comparing @FindBy and Map repository approaches | rafazzevedo

  7. Hi Bas,

    what are the advantages if say ill just assign all elements using WebElement directly over using @FindBy annotation?

    currently i am not using @FindBy annotation and Pagefactory. What im implementing is assigning all elements using WebElement then accessing all my page methods in test class by instantiating my page object class.

    im just confused if ill proceed with rewriting my script to adopt page factory design.

    • Hey Ken,

      as usual: it depends. One feature of the PageFactory is that every time an object created using the PageFactory (with @FindBy) is referenced in your code, it is searched again automatically by the driver object. This is a good thing when you’re using an AJAX-heavy page with a lot of front-end processing going on. If you’d use your approach for such a web page, then the risk of the object not being there when you reference it (resulting in either a NoSuchElementException or more likely a StaleElementReferenceException) will increase.

      If, on the other hand, you’re pretty sure that your object will be there at the time of reference (of course you still need to provide some error handling), then there’s no real advantage of using the PageFactory.

      Personally I’m not too big a fan of the PageFactory pattern either, if only because it doesn’t support dynamic ID’s (for example XPath expressions that contain a variable whose value is to be determined at runtime).

      • Thanks for the response.

        in connection with the topic, i wanna know how to use @FindBys/All in selecting items in the dropdown. my implementation is ill create a random number based on the length of items in the dropdown. the random number will be the selection for which the item selected. will it be possible in using this annotation?

        same with selecting a date from a jquery datepicker. can it be possible with this annotation?

        • I don’t think that’s a very good idea. Why would you want to build (pseudo-)randomness like that into your tests? Automated checks are all about predictability, having randomness in them will very likely only lead to flaky tests and test code that is harder to maintain..

          • it is just for selecting items in the dropdown. i dont want to select the same item all throughout my tests. somehow when i make it random i can select other items w/o creating a test for each. its a lazy approach though. ๐Ÿ™‚

            any suggestion how will i go about the scenario? Thanks

  8. Hi Bas,

    Can Something like:

    List element = driver.findEleemnt(“an id “)).findElements(By.tagName(“tr”)) is possible using these find annotation. If yes kindly give any small code example.

    • Hi Keshav,

      that’s not going to work probably. The first driver.findElement() returns only a single element (at most), what’s the point of the second findElements() in that case? You already have a specific element. It might be useful the other way around (first select a number of elements that have the

      tag, then select from that subset the one with id ‘an id’). I think you’re better off writing an appropriate CSS or XPath selector in that case, because it will only search the DOM once.
  9. Hi Bas,

    I am not getting use of


    While we have direct

    in POM

    and When we use @FindAll And @FindBys annotaion In POM

  10. Pingback: Understanding FindsBy in Selenium | Selenium Bytes

  11. Hi Bas,

    we have big test project for our web app. It has dozens on classes separated in packagase – test classes, parameters, page classes, constants.

    Naturally the project contains thousands of webelements. What we do now is that at the beginning of each page class we define all objectst on that page using @FindBy and then the methods for defined objects (fill form etc.).

    Problem is that we have a lot of elements on each page and it makes our classes too long and not so easy to read.

    We have also the problem that we can not use variables in selectors using @FindBy (as you mentioned before) and it would be really helpful sometimes.

    We are thinking to put our selectors to string constants and put variables in them using String.format(). Then we define object in method where we use it:
    WebElement filterButton = driver.findElement(By.xpath(String.format(XPATH_FILTER_BUTTON, columnName)));;

    What do you think about tis approach? Do you have any suggestion for web elements definition in big projects?

    • The String.format option sounds good, I used to do this with simple string concatenation but this is even better.

      And if your classes are getting too big then you simply need to refactor them and split them up in smaller classes (one for each form, for example). Or you could take a look at the Screenplay pattern as an alternative to the Page Object pattern, but that would probably require a lot of rework..

      Hope that helps! If not, do let me know.

  12. Hi there!

    Is there any way to find elements based on a parent element using the FindBy annotations? I’m using C# btw.

    Great post!

      • consider i have defined 2 elements using @Findby as below :

        private WebElement txt_username;

        private WebElement txt_password;

        and due to incorrect xpath both the findby fails. (noSuchElementFound)
        MyQuestion is , How to catch exception and display which element failed ?

        (hope im clear this time ๐Ÿ™‚ )

        • Yeah I see what you’re trying to do now. I can’t think of an elegant way to do this using the PageFactory. I don’t even particularly like the PageFactory, if only because it doesn’t support dynamic locators (with variables in them). One alternative is to use wrapper methods around the Selenium API calls (hey look, here’s a blog post on that) and write some decent debugging / failure info to your output of choice. In that way, you know exactly what element couldn’t be found AND you can deal with dynamic locators.

  13. hi Bas,

    I am using @FindBy annotation in my code in the below form.

    WebElement auditbutton;

    the xpath is correct and i am clicking on the webelement taht i have defined.But i am getting null pointer exception.
    Is it that @FindBy annotation runs with some particular version of testng.
    Please help me on this.

    Thanks in advance

  14. Nice Post, i had a quick question the way i was using to @Find was simple using classname but i get

    org.openqa.selenium.ElementNotVisibleException: element not visible
    at com.sun.proxy.$ Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(
    at java.lang.reflect.Method.invoke(
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(
    at org.junit.internal.runners.statements.RunBefores.evaluate(
    at org.junit.internal.runners.statements.RunAfters.evaluate(
    at org.junit.runners.ParentRunner.runLeaf(
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(
    at org.junit.runners.ParentRunner$
    at org.junit.runners.ParentRunner$1.schedule(
    at org.junit.runners.ParentRunner.runChildren(
    at org.junit.runners.ParentRunner.access$000(
    at org.junit.runners.ParentRunner$2.evaluate(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(

    • Hey Gopal,

      that simply means the element is not visible at the time it was referenced in your script. This probably has nothing to do with using Page Factory.

  15. HI Bas, i am automating a native app, So interacting with UIA elements as UIAButton , UIAStaticText ect. Unlike Web, While using @FindBy (UIA – Xpath) – say. its taking much longer time. Is there any other way to find it fast

  16. Hi Sir I am getting java.lang.NullPointerException in below code, please help

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.firefox.FirefoxDriver;

    public class FindByone {
    WebDriver driver;
    private WebElement Downloadlink;

    public void onee() {
    driver = new FirefoxDriver();

    public static void main(String[] args) {

    FindByone obj = new FindByone();

    • Hey Ashwini,

      that’s because you’re not using the PageFactory properly to initialize the element. You could do one of two things:

      • Properly implement the Page Factory, possibly in conjunction with the Page Object Model
      • Replace the @FindBy(id=”q”) private WebElement DownloadLink and replace Downloadlink.sendKeys(โ€œLoginโ€); with driver.findElement(“q”)).sendKeys(“Login”);

      For a simple test like yours I’d suggest the second option.

      • Sir I want to go with option 1 you mentioned. here in my code I need to understand what I did wrong which is giving me java.lang.NullPointerException on this line Downloadlink.sendKeys(โ€œLoginโ€);
        Sir could you please make the required correction in code and then past the code again for me.

        • I have made changes in my code and Properly implemented the Page Factory but this time I am getting this error, I think somewhere I am making small mistake if you help in fixing that would be great help
          Exception in thread “main” java.lang.NullPointerException
          at com.sun.proxy.$ Source)
          at FindByone.onee(
          at FindByone.lastmethod(
          at FindByone.main(

          Below is the updated code

          import java.util.concurrent.TimeUnit;

          import org.openqa.selenium.By;
          import org.openqa.selenium.WebDriver;
          import org.openqa.selenium.WebElement;
          import org.openqa.selenium.firefox.FirefoxDriver;

          public class FindByone {
          static WebDriver driver;
          public WebElement Downloadlink;
          public FindByone(WebDriver driver){
          FindByone.driver = driver;
          PageFactory.initElements(driver, this);

          public void onee() {
          driver = new FirefoxDriver();
          driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
          driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

          public void lastmethod(){


          public static void main(String[] args) {

          FindByone obj = new FindByone(driver);

          • Have you tried debugging your code? I could do that for you but I’d rather you learn how to do that yourself ๐Ÿ™‚

        • Hi Ashwini ,

          Could u plz chk whr u instantiate the elements to drivr that’s d problm.u want to do dis way, u hav to mad class ex.util and mthods i.e. for input ex. getUtilobj and one for driver ex. getdrivr
          To instantiate the elements
          then PageFactory.initElements(util .getUtilobj().getdrivr() , this);

          I cud not find dirct way…

  17. Hi!

    I’m using pagefactory pattern and I would like to grab a list from the site.

    private list list;

    The problem is that here, I got a list, but returns only one size list. So list.get(0) has all the data divided by a space.

    How can I get a proper list instead of one element list?

    Thank you!


    • If all spaces can be regarded as item separators (i.e., there are no item values that also have a space in them) you could split the string into an array based on the space separator and work from there.

  18. Hi Bas,

    What are the advantages of initializing all elements with PageFactory.initElements() ?
    Couldn’t we just initialize it once we need it ?? once we what to interact with the element?

    • Honest answer? Yes, it’s perfectly fine to not use the PageFactory. I’ve never used it myself. I’d rather have Selenium look up the element at the moment I need as well, just like you said.

      The only purpose of the test is to explain the workings of the @FindBy annotation for those who do use it.

      • Thanks for your response. So, I have another question…will it be used for elements changing their locators dynamically.

        I want to access a string from xls and want to generate web element.

        public WebElement element;
        Is there a way I can do above scenario

        • Not that I know of. And that’s one reason I don’t use PageFactory at all. The other main reason being that it’s much easier to use wrapper methods instead, and more stable to boot.

  19. Hello Bas,

    Loved you article!
    We are making out automation using Protractor, Jasmine and WebStorm, so my question is, is there a way for us to use this technique ?

    • I have no idea whether protractor supports the PageFactory pattern (I think it doesn’t because a quick Google search didn’t turn up anything).

    • Also, I think the PageFactory is not really a useful pattern, I don’t generally use it myself. But that’s a whole different blog post ๐Ÿ™‚

  20. How to use %s with WebElement :

    @FindBy(xpath=”//div[@class=’monthBlock first’]/div/div/span[text()=’%s’]/../span[text()=’%s’]’]/div/a”) WebElement MONTH_YEAR_LABEL

    Can you please explain this scenario?

    • I assume you use the %s for string formatting? I don’t know if that makes sense in this case. Not a fan of PageFactory so I don’t know if this would work at all.

  21. Hi Bas,
    How are you? i am new to selenium. i do not know what is page factory. could you please explain it in simple terms??

    • Hi Neeraj,

      basically, PageFactory is a pattern that has been created to make it easier to find elements on a web page and initialize WebElement objects in your code.

      Personally, I don’t use it though. I prefer the strategy of defining locators using a By object and passing them to helpers methods that find the element at the moment it is needed. Gives me more flexibility with regards to error handling and I’m sure that the element is initialized at the right moment (i.e., when I need it). I’ve used and explained this approach in this post.

  22. Pingback: Selenium Vicky_pedia – VikramVI Knowledge Sharing

Leave a Reply

Your email address will not be published. Required fields are marked *