Can Python Solve Sudoku in Seconds? Automate with Selenium & Backtracking

Learn how to automate a web-based Sudoku game using Python's Selenium for data extraction, implement an efficient backtracking and bitwise algorithm to solve the puzzle, and programmatically fill the solution back into the browser, achieving performance improvements from 17 seconds to just over 3 seconds.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Can Python Solve Sudoku in Seconds? Automate with Selenium & Backtracking

This article demonstrates how to use Python and Selenium to automatically solve a Sudoku puzzle hosted on a web page, extract the board data, compute the solution with an optimized backtracking algorithm, and write the solved numbers back into the browser.

Sudoku Rules

Each digit 1‑9 must appear exactly once in every row.

Each digit 1‑9 must appear exactly once in every column.

Each digit 1‑9 must appear exactly once in each 3×3 sub‑grid.

Accessing the Target Site with Selenium

First install Selenium and then open a Chrome browser instance:

from selenium import webdriver
browser = webdriver.Chrome()

Navigate to the Sudoku page:

url = "https://www.sudoku.name/index.php?ln=cn&puzzle_num=&play=1&difficult=4&timer=&time_limit=0"
browser.get(url)

Extracting Sudoku Data

The puzzle is rendered inside a table element with id sudoku_main_board. Each cell is an input whose value attribute holds the digit or is empty.

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

wait = WebDriverWait(browser, 10)
table = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'table#sudoku_main_board')))

board = []
for tr in table.find_elements_by_xpath('.//tr'):
    row = []
    for input_e in tr.find_elements_by_xpath('.//input[@class="i3"]'):
        cell = input_e.get_attribute('value')
        row.append(cell if cell else '.')
    board.append(row)
board

The extracted board is a list of lists where empty cells are represented by ..

Solving Sudoku with Backtracking and Bitwise Optimization

The initial solver uses classic backtracking with bitwise masks to track used digits in rows, columns, and blocks:

def solveSudoku(board):
    def flip(i, j, digit):
        line[i] ^= (1 << digit)
        column[j] ^= (1 << digit)
        block[i // 3][j // 3] ^= (1 << digit)

    def dfs(pos):
        nonlocal valid
        if pos == len(spaces):
            valid = True
            return
        i, j = spaces[pos]
        mask = ~(line[i] | column[j] | block[i // 3][j // 3]) & 0x1ff
        while mask:
            digitMask = mask & (-mask)
            digit = bin(digitMask).count('0') - 1
            flip(i, j, digit)
            board[i][j] = str(digit + 1)
            dfs(pos + 1)
            flip(i, j, digit)
            mask &= (mask - 1)
            if valid:
                return

    line = [0] * 9
    column = [0] * 9
    block = [[0] * 3 for _ in range(3)]
    valid = False
    spaces = []
    for i in range(9):
        for j in range(9):
            if board[i][j] == '.':
                spaces.append((i, j))
            else:
                digit = int(board[i][j]) - 1
                flip(i, j, digit)
    dfs(0)

Running this version on the sample board took about 17 seconds.

Optimization idea: if a blank cell has only one possible digit (its mask contains a single bit), fill it immediately instead of waiting for recursion.

Optimized Solver

The refined implementation adds a deterministic filling pass before recursion, reducing runtime to roughly 3.2 seconds:

def solveSudoku(board: list) -> None:
    def flip(i: int, j: int, digit: int):
        line[i] ^= (1 << digit)
        column[j] ^= (1 << digit)
        block[i // 3][j // 3] ^= (1 << digit)

    def dfs(pos: int):
        nonlocal valid
        if pos == len(spaces):
            valid = True
            return
        i, j = spaces[pos]
        mask = ~(line[i] | column[j] | block[i // 3][j // 3]) & 0x1ff
        while mask:
            digitMask = mask & (-mask)
            digit = bin(digitMask).count('0') - 1
            flip(i, j, digit)
            board[i][j] = str(digit + 1)
            dfs(pos + 1)
            flip(i, j, digit)
            mask &= (mask - 1)
            if valid:
                return

    line = [0] * 9
    column = [0] * 9
    block = [[0] * 3 for _ in range(3)]
    valid = False
    spaces = []
    for i in range(9):
        for j in range(9):
            if board[i][j] != '.':
                digit = int(board[i][j]) - 1
                flip(i, j, digit)
    while True:
        modified = False
        for i in range(9):
            for j in range(9):
                if board[i][j] == '.':
                    mask = ~(line[i] | column[j] | block[i // 3][j // 3]) & 0x1ff
                    if not (mask & (mask - 1)):
                        digit = bin(mask).count('0') - 1
                        flip(i, j, digit)
                        board[i][j] = str(digit + 1)
                        modified = True
        if not modified:
            break
    for i in range(9):
        for j in range(9):
            if board[i][j] == '.':
                spaces.append((i, j))
    dfs(0)

Writing the Solution Back to the Web Page

After solving, the script iterates over the same table cells and uses Selenium to click, clear, and send the solved digit:

for i, tr in enumerate(table.find_elements_by_xpath('.//tr')):
    for j, input_e in enumerate(tr.find_elements_by_xpath('.//input[@class="i3"]')):
        if input_e.get_attribute('readonly') == 'true':
            continue
        input_e.click()
        input_e.clear()
        input_e.send_keys(board[i][j])

The automation fills the entire puzzle in a few seconds, turning a manual 14‑minute effort into a 10‑second completion.

Sudoku game interface
Sudoku game interface
Solved Sudoku animation
Solved Sudoku animation
Performance improvement screenshot
Performance improvement screenshot
PythonAutomationbitwiseBacktrackingweb-scrapingseleniumsudoku
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.