My situation:
I’m trying to build an automated WhatsApp messaging system that runs on a remote server. Here’s what I want to do:
- Read contact numbers from a Google spreadsheet
- Process this data using Python scripts
- Launch WhatsApp Web automatically to send bulk messages
I have working code that runs fine on my local computer with a visible browser:
browser = webdriver.Chrome()
browser.get('https://web.whatsapp.com/')
wait_element = WebDriverWait(browser, 30)
login_attempts = 0
while True:
try:
wait_element.until(EC.presence_of_element_located((By.XPATH, "//canvas[@aria-label='Scan me!']")))
login_attempts += 1
if login_attempts % 500 == 0:
print("Still waiting for QR scan...")
except:
print("Successfully logged into WhatsApp")
break
for contact in contact_list:
browser.find_element_by_xpath(CONTACT_INPUT_FIELD).send_keys(str(contact['Number']))
time.sleep(1)
browser.find_element_by_xpath(CONTACT_INPUT_FIELD).send_keys(Keys.ENTER)
time.sleep(1)
browser.find_element_by_class_name('message_input').send_keys(str(contact['Text']))
time.sleep(1)
browser.find_element_by_class_name('send_button').click()
time.sleep(1)
The problem:
When I try to run this headless, I can’t complete the QR code authentication step. My headless setup fails with element not found errors:
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
browser = webdriver.Chrome(options=options)
def automate_whatsapp():
browser.get('https://web.whatsapp.com/')
for contact in contact_list:
browser.find_element_by_xpath("//div[@contenteditable='true']").send_keys(str(contact['Number']))
time.sleep(1)
browser.find_element_by_xpath("//div[@contenteditable='true']").send_keys(Keys.ENTER)
time.sleep(1)
browser.find_element_by_class_name('message_input').send_keys(str(contact['Text']))
time.sleep(1)
browser.find_element_by_class_name('send_button').click()
time.sleep(1)
print(f"Message sent to {contact['Number']} - {contact['Name']}")
Is there any way to handle WhatsApp Web authentication in headless mode? I’m open to using different Python libraries if needed.