Install & Compatibility
Where this runs
tested against v1.4.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 1.030s · 34.6MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 3.0s · import 0.948s · 35MB
33MB installed
● package 33MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
StatefulBrowser
✓ from mechanicalsoup import StatefulBrowser
Browser
✓ from mechanicalsoup import Browser
Form
✓ from mechanicalsoup import Form
✗ from mechanicalsoup.form import Form
Form is directly exposed by the top-level package in recent versions.
This quickstart demonstrates how to initialize a `StatefulBrowser`, set its content (or open a URL), select a form, fill its fields, and prepare to submit it. For actual interaction with a website, replace the `set_content` call with `browser.open("http://your.site/login")` and uncomment the submission and response handling lines.
import mechanicalsoup
import os
# Create a headless browser instance
browser = mechanicalsoup.StatefulBrowser()
# Open a page (replace with a real URL for testing, e.g., a login page)
# For a test, we'll use a mock login setup
# In a real scenario, you'd open a target URL:
# browser.open("http://example.com/login")
# Simulate a simple HTML page with a form
# For demonstration, we'll parse a string. In reality, browser.open() returns a response.
html_content = '''
<html><body>
<form action="/login" method="post">
<input type="text" name="username" value="">
<input type="password" name="password" value="">
<input type="submit" value="Login">
</form>
</body></html>
'''
browser.set_content(html_content)
# Select the form (by index or CSS selector)
browser.select_form('form[action="/login"]')
# Fill in the form fields
browser["username"] = os.environ.get('TEST_USERNAME', 'testuser')
browser["password"] = os.environ.get('TEST_PASSWORD', 'testpass')
# Submit the form
# In a real scenario, this would send the request to the action URL
# response = browser.submit_selected()
print(f"Form selected: {browser.form}")
print(f"Username field value: {browser['username']}")
print(f"Password field value: {browser['password']}")
# print(f"Response URL after submission: {browser.url}")
# print(f"Response content: {browser.page.text}")
Errors
Common errors & fixes
FileNotFoundError: [Errno 2] No such file or directory: '/path/to/file'
Attempting to upload a file in MechanicalSoup 1.3.0+ by passing a string path directly to a form field, instead of an opened file object.
fixPass an explicitly opened file object: `browser["upload_field"] = open("/path/to/file.txt", "rb")`. Remember to close the file handle after submission if not managed automatically. AttributeError: 'StatefulBrowser' object has no attribute 'get_current_page'
Using an old, deprecated method (`get_current_page`, `get_current_form`, or `get_url`) after upgrading to MechanicalSoup 1.0.0+ where these might be removed or not correctly mapped in some contexts (though generally still present as of 1.4.0, it's a common confusion point).
fixUse the direct properties introduced in 1.0.0: `browser.page`, `browser.form`, `browser.url`.
mechanicalsoup.LinkNotFoundError: No link found with selector 'a.broken-link'
The specified link selector did not match any link on the current page, or a 404 Not Found error occurred and `raise_on_404` is enabled for the browser.
fixVerify your link selector is correct and matches an existing link. If you're getting 404s, consider if the URL is valid, or if you need to handle `LinkNotFoundError` if `raise_on_404=True`.
ValueError: No form selected
Attempting to interact with form fields (e.g., `browser['field_name'] = 'value'`) or submit a form without first successfully selecting one using `browser.select_form()`.
fixEnsure `browser.select_form()` is called with a valid selector (e.g., `browser.select_form('form[action="/login"]')`) before trying to manipulate form fields or submit. Upgrade
Version history
1.4.0latest on PyPI · released May 30, 2025
Audit
Dependencies
requestsrequiredUsed for making HTTP requests, minimum version increased in 1.1.0.
beautifulsoup4requiredUsed for parsing HTML and navigating the DOM, minimum version increased in 1.1.0.
urllib3requiredUnderlying HTTP client, minimum version specified in 1.4.0 to mitigate security vulnerabilities.
certifirequiredProvides Mozilla's carefully curated collection of Root Certificates for validating the trustworthiness of SSL certificates, minimum version specified in 1.4.0.
lxmloptionalDefault (and recommended) HTML parser, part of `mechanicalsoup[full]` install.
html5liboptionalAlternative HTML parser, part of `mechanicalsoup[full]` install.