I am trying to perform an automatic login with Selenium. My code keeps getting stuck at password_field.send_keys(Keys.RETURN): The browser window accepts that the data has been entered and return has been pressed, but then the page loads and stays in this mode forever without going any further. The lines after this are therefore not executed. I have already written the code so that password_field.send_keys(Keys.RETURN) and the remaining part are separated and it runs asynchronously, but the same problem occurs. import requests import base64 import secrets import hashlib import webbrowser from http.server import HTTPServer, BaseHTTPRequestHandler from urllib.parse import urlparse, parse_qs from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys # Generate PKCE code verifier and challenge (recommended for public clients) def generate_pkce_pair(): code_verifier = secrets.token_urlsafe(64) code_challenge = ( base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()) .decode() .rstrip("=") ) return code_verifier, code_challenge # Callback handler to receive the authorization code class CallbackHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-Type", "text/html") self.end_headers() # Extract authorization code from URL query parameters query_components = parse_qs(urlparse(self.path).query) if "code" in query_components: # Store the auth code in the server instance self.server.auth_code = query_components["code"][0] # Display success message to the user self.wfile.write( b"<html><body><h1>Authentication successful!</h1><p>You can close this window now.</p></body></html>" ) else: # Handle error or cancel self.wfile.write( b"<html><body><h1>Authentication failed!</h1><p>No authorization code received.</p></body></html>" ) self.server.auth_code = None # Signal that we have processed the callback self.server.handled = True def get_webpage_resp(): # Generate PKCE code pair code_verifier, code_challenge = generate_pkce_pair() # Create the authorization URL auth_url = ( f"{auth_endpoint}" f"?client_id={CLIENT_ID}" f"&response_type=code" f"&redirect_uri={REDIRECT_URI}" f"&scope={SCOPE}" f"&code_challenge={code_challenge}" f"&code_challenge_method=S256" f"&state={secrets.token_urlsafe(16)}" # State parameter to prevent CSRF ) # Replace 'your_path_to_webdriver' with the path to your WebDriver executable driver = webdriver.Chrome() # Open the webpage driver.get(auth_url) # Fill out form fields by finding them by name, id, or other attributes username_field = driver.find_element(By.ID, 'username') password_field = driver.find_element(By.ID, 'password') username_field.send_keys('blabla_user') password_field.send_keys('blabla_pwd') # Start local server to receive the callback server = HTTPServer(("localhost", 8000), CallbackHandler) server.auth_code = None server.handled = False # Send the Enter/Return key to any of the form fields password_field.send_keys(Keys.RETURN) # Wait for the callback to be processed print("Waiting for authentication callback...") while not server.handled: server.handle_request() # Close the browser driver.quit() auth_code = server.auth_code if not auth_code: print("Authentication failed: No authorization code received") return print(f"Authorization code received: {auth_code}") # Exchange authorization code for tokens token_data = { "grant_type": "authorization_code", "code": auth_code, "redirect_uri": REDIRECT_URI, "client_id": CLIENT_ID, "code_verifier": code_verifier, } # Add client secret for confidential clients headers = {"Content-Type": "application/x-www-form-urlencoded"} if CLIENT_SECRET: token_data["client_secret"] = CLIENT_SECRET # Request tokens response = requests.post(token_endpoint, data=token_data, headers=headers) if response.status_code == 200: tokens = response.json() print("Authentication successful!") print(f"Access Token: {tokens['access_token'][:20]}...") if "refresh_token" in tokens: print(f"Refresh Token: {tokens['refresh_token'][:20]}...") # Now you can use the access token to call your API # Example API call: api_response = requests.get( "https://some-adress", headers={"Authorization": f"Bearer {tokens['access_token']}"}, ) print(api_response.text) else: print(f"Token request failed: {response.status_code}") print(response.text) return response If I wait, I get the following error message: ReadTimeoutError Traceback (most recent call last) Cell In[2], line 1 ----> 1 get_webpage_resp() File /media/tw/Daten/Peak/locust/oauth_webpage_click_simulator.py:110, in get_webpage_resp() 103 server.handled = False 105 # muss gemacht werden, sonst hängt die Seite 106 #driver.set_page_load_timeout(10) 107 # driver.refresh() 108 109 # Send the Enter/Return key to any of the form fields --> 110 password_field.send_keys(Keys.RETURN) 112 driver.get(REDIRECT_URI) 114 # Wait for the callback to be processed File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webelement.py:303, in WebElement.send_keys(self, *value) 300 remote_files.append(self._upload(file)) 301 value = tuple("\n".join(remote_files)) --> 303 self._execute( 304 Command.SEND_KEYS_TO_ELEMENT, {"text": "".join(keys_to_typing(value)), "value": keys_to_typing(value)} 305 ) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webelement.py:572, in WebElement._execute(self, command, params) 570 params = {} 571 params["id"] = self._id --> 572 return self._parent.execute(command, params) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:427, in WebDriver.execute(self, driver_command, params) 424 elif "sessionId" not in params: 425 params["sessionId"] = self.session_id --> 427 response = self.command_executor.execute(driver_command, params) 428 if response: 429 self.error_handler.check_response(response) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:404, in RemoteConnection.execute(self, command, params) 402 trimmed = self._trim_large_entries(params) 403 LOGGER.debug("%s %s %s", command_info[0], url, str(trimmed)) --> 404 return self._request(command_info[0], url, body=data) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:428, in RemoteConnection._request(self, method, url, body) 425 body = None 427 if self._client_config.keep_alive: --> 428 response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout) 429 statuscode = response.status 430 else: File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/_request_methods.py:143, in RequestMethods.request(self, method, url, body, fields, headers, json, **urlopen_kw) 135 return self.request_encode_url( 136 method, 137 url, (...) 140 **urlopen_kw, 141 ) 142 else: --> 143 return self.request_encode_body( 144 method, url, fields=fields, headers=headers, **urlopen_kw 145 ) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/_request_methods.py:278, in RequestMethods.request_encode_body(self, method, url, fields, headers, encode_multipart, multipart_boundary, **urlopen_kw) 274 extra_kw["headers"].setdefault("Content-Type", content_type) 276 extra_kw.update(urlopen_kw) --> 278 return self.urlopen(method, url, **extra_kw) File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/poolmanager.py:443, in PoolManager.urlopen(self, method, url, redirect, **kw) 441 response = conn.urlopen(method, url, **kw) 442 else: --> 443 response = conn.urlopen(method, u.request_uri, **kw) 445 redirect_location = redirect and response.get_redirect_location() 446 if not redirect_location: File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:841, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw) 838 elif isinstance(new_e, (OSError, HTTPException)): 839 new_e = ProtocolError("Connection aborted.", new_e) --> 841 retries = retries.increment( 842 method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2] 843 ) 844 retries.sleep() 846 # Keep track of the error for the retry warning. File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/util/retry.py:474, in Retry.increment(self, method, url, response, error, _pool, _stacktrace) 471 elif error and self._is_read_error(error): 472 # Read retry? 473 if read is False or method is None or not self._is_method_retryable(method): --> 474 raise reraise(type(error), error, _stacktrace) 475 elif read is not None: 476 read -= 1 File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/util/util.py:39, in reraise(tp, value, tb) 37 if value.__traceback__ is not tb: 38 raise value.with_traceback(tb) ---> 39 raise value 40 finally: 41 value = None # type: ignore[assignment] File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:787, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw) 784 response_conn = conn if not release_conn else None 786 # Make the request on the HTTPConnection object --> 787 response = self._make_request( 788 conn, 789 method, 790 url, 791 timeout=timeout_obj, 792 body=body, 793 headers=headers, 794 chunked=chunked, 795 retries=retries, 796 response_conn=response_conn, 797 preload_content=preload_content, 798 decode_content=decode_content, 799 **response_kw, 800 ) 802 # Everything went great! 803 clean_exit = True File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:536, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length) 534 response = conn.getresponse() 535 except (BaseSSLError, OSError) as e: --> 536 self._raise_timeout(err=e, url=url, timeout_value=read_timeout) 537 raise 539 # Set properties that are used by the pooling layer. File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:367, in HTTPConnectionPool._raise_timeout(self, err, url, timeout_value) 364 """Is the error actually a timeout? Will raise a ReadTimeout or pass""" 366 if isinstance(err, SocketTimeout): --> 367 raise ReadTimeoutError( 368 self, url, f"Read timed out. (read timeout={timeout_value})" 369 ) from err 371 # See the above comment about EAGAIN in Python 3. 372 if hasattr(err, "errno") and err.errno in _blocking_errnos: ReadTimeoutError: HTTPConnectionPool(host='localhost', port=33877): Read timed out. (read timeout=120) Continue reading...