MechanicalSoup
Python library for automating website interaction — form submission, cookie handling, link following. Built on requests + BeautifulSoup. Current version is 1.4.0 (2023). Install name is MechanicalSoup (capital M and S), import is mechanicalsoup (all lowercase). Does NOT execute JavaScript — use Playwright or Selenium for JS-rendered pages. Maintenance status: low activity since 2023.
Warnings
- breaking MechanicalSoup does NOT execute JavaScript. Pages that render content via JS (React, Vue, Angular SPAs) will appear empty or broken. This is the most common misuse.
- gotcha Install name and import name differ in capitalization. pip install MechanicalSoup (capital M and S), but import mechanicalsoup (all lowercase). import MechanicalSoup raises ModuleNotFoundError.
- gotcha raise_on_404=False by default — 404 responses are silently treated as successful. Code that navigates to a missing page gets no error and browser.page will contain the 404 HTML.
- gotcha Browser (stateless) and StatefulBrowser (stateful) have different APIs. Browser.get() returns a response. StatefulBrowser.open() returns a response AND updates internal state. Mixing them causes confusion.
- gotcha select_form() with no argument selects the first form on the page. On pages with multiple forms (login + newsletter), this may select the wrong form.
Install
-
pip install MechanicalSoup
Imports
- StatefulBrowser
import mechanicalsoup # StatefulBrowser remembers state (cookies, current page) browser = mechanicalsoup.StatefulBrowser( soup_config={'features': 'lxml'}, raise_on_404=True # recommended: raise on 404 instead of silently failing ) browser.open('https://example.com/login') browser.select_form('#login-form') browser['username'] = 'alice' browser['password'] = 'secret' browser.submit_selected()
Quickstart
import mechanicalsoup
# StatefulBrowser is the high-level interface
browser = mechanicalsoup.StatefulBrowser(
soup_config={'features': 'lxml'},
raise_on_404=True
)
# Navigate to a page
browser.open('https://httpbin.org/forms/post')
# Select and fill a form
browser.select_form('form') # or CSS selector like '#login-form'
browser['custname'] = 'Alice'
browser['custtel'] = '555-1234'
browser['comments'] = 'Hello!'
# Submit the form
response = browser.submit_selected()
print(response.status_code)
# Access the resulting page
print(browser.page.title.string)