Open JasonGross opened 1 month ago
For future reference, I debugged this with
try:
await self.page.frame(name=login_frame).press("[placeholder=\"Password\"]", "Enter")
await self.page.wait_for_url(re.compile(r"app/trade"), wait_until="domcontentloaded") # Making it more robust than specifying an exact url which may change.
except TimeoutError as e:
# Capture screenshot
await self.page.screenshot(path="debug_screenshot.png")
# Save page content
page_content = await self.page.content()
with open("debug_page_content.html", "w", encoding="utf-8") as f:
f.write(page_content)
print(f"Current URL: {self.page.url}")
raise RuntimeError(f"Login was not successful; please check username and password. Debug info saved to {os.path.abspath('debug_screenshot.png')} and {os.path.abspath('debug_page_content.html')}") from e
If Voice ID is partially set up, the login page redirects to https://client.schwab.com/service/forms/VoiceBiometric instead of whichever page was selected: The relevant HTML fragment for clicking "Cancel", which just skips voice activation enabling and going to the correct post-login page, is
(Full page html is voice_activation_page_redacted.html.zip) It would be nice if https://github.com/itsjafer/schwab-api/blob/4ecc6242c58d93c6423bca2f1aa06e2260f25b31/schwab_api/authentication.py#L167 would also wait for
service/forms/VoiceBiometric
, and cancel if necessary.