Hack of the day: change your Netflix password from the command line

By | July 11, 2018

My kids watch a lot of Netflix. Some of them watch it too much, and my wife and I want to be able to turn off the spigot at night so that they’ll go to sleep without us having to confiscate all the phones and tablets in the house. Unfortunately, Netflix doesn’t have parental controls that make this possible (in particular, they would need to support protecting profiles with PINs and time- and profile- based access restrictions). We therefore came up with the idea of changing our Netflix password at bedtime every night and changing it back in the morning.

However, there’s no way we can sustain logging into Netflix in a browser and changing our password twice a day, morning and night, so we need to we need to find a way to automate that.

Netflix doesn’t provide any sort of public API for things like that. OK, fine, whatever, I’m fluent in Perl’s WWW::Mechanize and Python’s mechanize, so I can just write a script to automate logging into my Netflix account and changing the password, right? Unfortunately, nope, it’s not that easy, because the password change page on the Netflix site is a funky React-based form, not a regular HTML form, so neither the Perl nor the Python library knows how to deal with it.

Fortunately, all is not lost: Selenium to the rescue!

#!/usr/bin/env python3
 
import argparse
from contextlib import contextmanager
import os
from selenium import webdriver
from selenium.webdriver.common.keys import Keys;
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import staleness_of
 
 
def parse_args():
    parser = argparse.ArgumentParser(description="Change Netflix password")
    parser.add_argument("--username", action="store", required=True)
    parser.add_argument("--old-password", action="store", required=True)
    parser.add_argument("--new-password", action="store", required=True)
    parser.add_argument("--headless", action="store_true", default=False)
    return parser.parse_args()
 
 
# Credit: http://www.obeythetestinggoat.com/how-to-get-selenium-to-wait-for-page-load-after-a-click.html
@contextmanager
def wait_for_page_load(driver, timeout=30):
    old_page = driver.find_element_by_tag_name('html')
    yield
    WebDriverWait(driver, timeout).until(staleness_of(old_page))
 
 
def main():
    args = parse_args()
 
    options = webdriver.ChromeOptions()
    if args.headless:
        options.add_argument('headless')
    driver = webdriver.Chrome(chrome_options=options)
    driver.get("https://www.netflix.com/login")
    elem = driver.find_element_by_name("email")
    elem.send_keys(args.username)
    elem = driver.find_element_by_name("password")
    elem.send_keys(args.old_password)
    elem.send_keys(Keys.RETURN)
    with wait_for_page_load(driver):
        driver.get("https://www.netflix.com/password")
    elem = driver.find_element_by_name("password")
    elem.send_keys(args.old_password)
    elem = driver.find_element_by_name("pw_new")
    elem.send_keys(args.new_password)
    elem = driver.find_element_by_name("pw_confirm")
    elem.send_keys(args.new_password)
    elem = driver.find_element_by_class_name("btn-submit")
    elem.click()
    with wait_for_page_load(driver):
        pass
 
 
if __name__ == '__main__':
    main()
Print Friendly, PDF & Email
Share

Leave a Reply

Your email address will not be published.