As you've mentioned

The class name has spaces in it, which lead me to use the css_selector

this is right approach, however you should also make sure that one

  1. One should remove the space and put a .
  2. . represent class in CSS.

So the below code should work:

driver.find_element(By.CSS_SELECTOR, ".btn.btn-alt.see-full-list-btn")

or you can even use it with the tag a

driver.find_element(By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn")

or the recommended solution would be to use with explicit waits:

see_full_list_button = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn")))
see_full_list_button.click()

Imports:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Answer from cruisepandey on Stack Overflow
๐ŸŒ
Readthedocs
cssselect.readthedocs.io
cssselect: CSS Selectors for Python โ€” cssselect 1.4.0 documentation
cssselect is a BSD-licensed Python library to parse CSS3 selectors and translate them to XPath 1.0 expressions.
๐ŸŒ
ScrapingBee
scrapingbee.com โ€บ webscraping-questions โ€บ css_selectors โ€บ how-to-use-css-selectors-in-python
How to use CSS Selectors in Python? | ScrapingBee
In Python, CSS selectors are primarily used to select one or more HTML elements while working with web pages, usually for scraping and browser automation.
Discussions

Css Selector button click with selenium (python) - Stack Overflow
I am trying to click on a button using selenium. My code states it is unable to find the css_selector with said class name. The class name has spaces in it, which lead me to use the css_selector ob... More on stackoverflow.com
๐ŸŒ stackoverflow.com
architecture - Hierachy and API design for a CSS-selector-related Python library - Software Engineering Stack Exchange
I'm writing a Python CSS-selector library that allows one to write these kinds of expressions in Python as a pet project. The goal of the library is to represent selectors in a flat, intuitive and More on softwareengineering.stackexchange.com
๐ŸŒ softwareengineering.stackexchange.com
October 27, 2023
python - How to located selenium element by css selector - Stack Overflow
I want to locate an element in selenium using css selector, and I use the program "copy css selector" and got: div>button[type ="submit"] Is this correct? submit_button = dr... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python: CSS Selector to use inside lxml.cssselect - Stack Overflow
I believe you cannot get the attribute value through CSS selectors. More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
GitHub
github.com โ€บ scrapy โ€บ cssselect
GitHub - scrapy/cssselect: CSS Selectors for Python ยท GitHub
cssselect is a BSD-licensed Python library to parse CSS3 selectors and translate them to XPath 1.0 expressions.
Starred by 310 users
Forked by 62 users
Languages ย  Python
๐ŸŒ
SerpApi
serpapi.com โ€บ blog โ€บ web-scraping-with-css-selectors-using-python
Web Scraping with CSS Selectors using Python
October 11, 2024 - Since SelectorGadget isn't a magical all around tool, sometimes it can't get the desired element. This happens when website HTML tree is not well structured, or if the site is rendered via JavaScript. When it happens, we use Elements tab via Dev Tools (F12 on a keyboard or CTRL+SHIFT+C) to locate and grab CSS selector(s) or HTML elements by their:
๐ŸŒ
Apify
blog.apify.com โ€บ python-css-selectors
Python CSS selectors and how to use them
March 21, 2024 - A short guide with examples of using CSS selectors with two popular Python libraries for web scraping: Beautiful Soup and Selenium.
Top answer
1 of 2
2

As you've mentioned

The class name has spaces in it, which lead me to use the css_selector

this is right approach, however you should also make sure that one

  1. One should remove the space and put a .
  2. . represent class in CSS.

So the below code should work:

driver.find_element(By.CSS_SELECTOR, ".btn.btn-alt.see-full-list-btn")

or you can even use it with the tag a

driver.find_element(By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn")

or the recommended solution would be to use with explicit waits:

see_full_list_button = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn")))
see_full_list_button.click()

Imports:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
2 of 2
0

There is no necessity to focus on the element HTML after the click is already invoked.

As per the HTML

<a href="#" class="btn btn-alt see-full-list-btn">See Full List</a>

you can use either of the following locator strategies:

  • Using link_text:

    driver.find_element(By.LINK_TEXT, "See Full List").click()
    
  • Using css_selector:

    driver.find_element(By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn").click()
    
  • Using xpath:

    driver.find_element(By.XPATH, "//a[@class='btn btn-alt see-full-list-btn' and text()='See Full List']").click()
    

Ideally to click on the clickable element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

  • Using LINK_TEXT:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "See Full List"))).click()
    
  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.btn.btn-alt.see-full-list-btn"))).click()
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='btn btn-alt see-full-list-btn' and text()='See Full List']"))).click()
    
  • Note: You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
๐ŸŒ
lxml
lxml.de โ€บ cssselect.html
lxml.cssselect
To use the selector, simply call it with a document or element object: >>> from lxml.etree import fromstring >>> h = fromstring('''<div id="outer"> ... <div id="inner" class="content body"> ... text ... </div></div>''') >>> [e.get('id') for e in sel(h)] ['inner'] Using CSSSelector is equivalent to translating with cssselect and using the XPath class:
Find elsewhere
๐ŸŒ
PyPI
pypi.org โ€บ project โ€บ cssselect
cssselect ยท PyPI
cssselect is a BSD-licensed Python library to parse CSS3 selectors and translate them to XPath 1.0 expressions.
      ยป pip install cssselect
    
Published ย  Jan 29, 2026
Version ย  1.4.0
๐ŸŒ
CodeSignal
codesignal.com โ€บ learn โ€บ courses โ€บ introduction-to-beautifulsoup-for-web-scraping โ€บ lessons โ€บ mastering-css-selectors-with-beautifulsoup-in-python-web-scraping
Mastering CSS Selectors with BeautifulSoup in Python ...
CSS Selectors are a powerful tool that allow you to pinpoint and extract precise information from a web page. Not only will you learn about the role of CSS selectors in web scraping, but also how to use these selectors with BeautifulSoup to scrape data effectively from a webpage using the power of Python.
๐ŸŒ
ScrapeOps
scrapeops.io โ€บ home โ€บ selenium web scraping playbook โ€บ python selenium find elements css
Python Selenium Guide - Finding Elements by CSS Selectors | ScrapeOps
January 8, 2024 - In this comprehensive guide, we will demystify the art of locating HTML elements using CSS Selectors with Selenium.
๐ŸŒ
Scrapfly
scrapfly.io โ€บ blog โ€บ how-to-use-css-selectors-in-python
How to use CSS Selectors in Python?
May 29, 2023 - from parsel import Selector soup = Selector(""" <a>link 1</a> <a>link 2</a> """) print(soup.css('a').get()) "<a>link 1</a>" print(soup.css('a').getall()) ["<a>link 1</a>", "<a>link 2</a>"]
๐ŸŒ
W3Schools
w3schools.com โ€บ cssref โ€บ css_selectors.php
CSS Selectors Reference
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT SWIFT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SWIFT SASS VUE GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING HTML & CSS BASH RUST TOOLS ยท CSS Reference CSS Browser Support CSS Selectors ...
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ find_element_by_css_selector-driver-method-selenium-python
find_element_by_css_selector() driver method - Selenium Python - GeeksforGeeks
July 12, 2025 - After you have installed selenium and checked out - Navigating links using the get method, you might want to play more with Selenium Python. After one has opened a page using selenium such as geeksforgeeks, one might want to click some buttons automatically or fill a form automatically or any such automated task. This article revolves around how to grab or locate elements in a webpage using locating strategies of Selenium Web Driver. More specifically, find_element(By.CSS_SELECTOR) is discussed in this article.
๐ŸŒ
Selenium Python
selenium-python.readthedocs.io โ€บ locating-elements.html
4. Locating Elements โ€” Selenium Python Bindings 2 documentation
ID = "id" NAME = "name" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector"
๐ŸŒ
WeasyPrint
doc.courtbouillon.org โ€บ cssselect2 โ€บ 0.3.0
cssselect2: CSS selectors for Python ElementTree โ€” cssselect2 0.3.0 documentation
A CSS selectors storage that can match against HTML elements. ... Add a selector and its payload to the matcher. ... payload โ€“ Some data associated to the selector, such as declarations parsed from the content of a style rule. It can be any Python object, and will be returned as-is by match().
Top answer
1 of 2
2

Because Python has very different syntax and semantics from CSS selectors, I think these problems will only get worse. You'll end up with something that doesn't look like CSS does and something that doesn't work like Python usually does. Therefore I would like to propose a different way of approaching the syntax.

CSS selectors are mostly a linear combination of simple selectors and combinators. I would suggest using that, and representing something like ns|p a:link as something like Tag('p', namespace='ns') + Descendant() + Tag('a') + PseudoClass('Link').

That is, you only use a single magic method to represent concatenation. Everything else is just regular Python objects, using regular Python constructors.

Your example could be

# lorem|foo.bar[baz^="qux"]:has(:invalid)::first-line
selector = Tag('foo', namespace='lorem) + \
           Class('bar') + \
           Attribute('baz', '^=', 'qux') + \
           PseudoClass('has', Selector.SELF + Descendant() + PseudoClass('invalid')) + \
           PseudoElement('first-line')

It may not be exactly what you were looking for, but it has the advantage that it is much easier to learn for Python users because it has much fewer rules and exceptions, and you don't need to worry about new selectors or incompatible syntax.

You can also use & instead of +, in which case you can represent a selector list with |, for example: p.warning, #bigwarning can become Tag('p') & Class('warning') | ID('bigwarning').


An alternative idea is to use no magic at all, and represent compound and/or complex selectors using lists or wrapper objects.

foo.bar > a might be something like Child([Tag('foo'), Class('Bar')], [Tag('a')]) (compound selectors are lists, complex selectors are wrapped by combinators) or [Tag('foo'), Class('bar'), Child(), Tag('a')] (complex selectors are lists containing the selectors).

The best option depends on ergonomics, and the ergonomics depend on how users will build and manipulate selectors and for what purpose.

2 of 2
1

You want to represent CSS concepts using valid python syntax which "looks like" the CSS source text.

Simplest approach would be stick with straight CSS source text, which we can roundtrip through deserializers and serializers. Representing punctuation-heavy CSS as python source will be inherently lossy, so you're going to have to store the details somewhere, perhaps in a global dict or in various """docstrings""".

It would be worthwhile to explicitly write down your various goals and tradeoffs. For example, getting IDE navigation / autocompletion "for free" might be one of the things you find attractive about your proposed scheme.

Python notation has been exploited for representing SI units, algebra, vector math, and pathnames. The notation is already a good fit for these domains, in some cases because the language strove to be a good fit. So lossless representation can often be achieved.

There are two mature problem domains that you might wish to take inspiration from.


sqlalchemy

The SQLAlchemy community uses at least one python DSL, arguably multiple ones, to represent SQL operations.

The impedance match is not perfect. Operator precedence is a bit of a rough edge, with a OR b turning into (a) | (b) when the two terms are complex. For some operators, such as IN, we resort to .in_() method call notation despite the in keyword seeming to be available.

Table or column names in principle can incorporate SPACE and many other characters, especially when "`" or other quoting mechanisms are used. But in practice DBAs will often choose to adhere to a conservative regex such as r("^\w+$"). Your approach might offer enough advantages that web designers would choose to adhere to conservative naming conventions, so e.g. "a-b" --> a_b --> "a-b" could be safely round-tripped.

SQL JOINs are commonly more than a hundred lines long, and a great many production queries have been recast to fit within this DSL.


type annotation

Type hinting continues to be something of a moving target in the python community. An application's source code might be read by an "old" or "new" interpreter, or type checker.

Expressing types in a back-compatible way for old interpreters or checkers has been a source of tension, often relieved via a string annotation escape valve. Forward references sometimes raise challenges that are resolved in the same way. In recent years we've had less need for this escape valve.

We see annotations appearing in the AST, and also in comment text.

The experiences of the type annotation community seem most relevant to your CSS goals.


Your goals are still a bit nebulous at this point. Several developer communities have traveled down this road, showing what works well, or poorly, or would work better after adopting some PEPs. You may be able to draw inspiration, learn from mistakes, and better predict a path to success by looking back at this history and incorporating some elements in your project goals.

๐ŸŒ
Scrapy
docs.scrapy.org โ€บ en โ€บ latest โ€บ topics โ€บ selectors.html
Selectors โ€” Scrapy 2.14.2 documentation
lxml is an XML parsing library (which also parses HTML) with a pythonic API based on ElementTree. (lxml is not part of the Python standard library.) Scrapy comes with its own mechanism for extracting data. Theyโ€™re called selectors because they โ€œselectโ€ certain parts of the HTML document specified either by XPath or CSS expressions.
๐ŸŒ
Python Examples
pythonexamples.org โ€บ python-selenium-find-element-by-css-selector
How to find Element by CSS Selector using Selenium Python
To find an HTML Element by CSS Selector using Selenium in Python, call find_element() method and pass By.CSS_SELECTOR as the first argument, and the CSS selector string (of the HTML Element we need to find) as the second argument.