Registry / http-networking / mechanicalsoup

mechanicalsoup

JSON →
library1.4.0pypypi✓ verified 86d ago

MechanicalSoup is a Python library for automating interaction with websites. It builds on top of `requests` and `BeautifulSoup4` to provide a stateful browser experience, making it easy to navigate, fill forms, and submit data without a full-fledged browser. The current version is 1.4.0, and it maintains a moderate release cadence, typically releasing minor versions every 6-12 months with occasional patch releases.

pip install mechanicalsoup
INSTALL
IMPORT
SIG · MECHANICALSOUP
M
mechanicalsoup
http-networkingpythonv1.4.0
Install
3.0s avg
Import
989ms
Disk
33MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
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
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 1.030s · 34.6MB
glibc
py 3.103.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}")
Debug
Known issues
breakingAs of v1.3.0, uploading files in forms requires explicitly opening the file object (e.g., `open('/path/to/file', 'rb')`) instead of just passing the file path as a string. This change was implemented to prevent malicious web servers from reading arbitrary local files.
fix
Instead of `browser['upload_field'] = '/path/to/file'`, use `browser['upload_field'] = open('/path/to/file', 'rb')`.
affects: >=1.3.0
breakingMechanicalSoup v1.4.0 dropped support for Python versions 3.6, 3.7, and 3.8. Earlier versions (v1.1.0) dropped 2.7 and 3.5. Ensure your environment uses Python 3.9 or higher.
fix
Upgrade your Python interpreter to version 3.9 or newer. For older Python versions, use MechanicalSoup < 1.4.0.
affects: >=1.4.0
gotchaSince v1.0.0, `StatefulBrowser` introduced properties (`.page`, `.form`, `.url`) to access the current page, form, and URL. The older method calls (`.get_current_page()`, `.get_current_form()`, `.get_url()`) are still present but are considered deprecated and may be removed in future versions.
fix
Prefer using the properties directly: `browser.page`, `browser.form`, `browser.url`.
affects: >=1.0.0
gotchaThe `StatefulBrowser` and `Browser` constructors accept a `raise_on_404=True` argument, which is highly recommended. By default, it's `False` for backward compatibility, meaning HTTP 404 errors might not immediately raise an exception, potentially leading to silent failures.
fix
Initialize your browser with `browser = mechanicalsoup.StatefulBrowser(raise_on_404=True)` to ensure `LinkNotFoundError` is raised on 404 responses.
affects: >=0.8.0
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.
fix
Pass 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).
fix
Use 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.
fix
Verify 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()`.
fix
Ensure `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.
Agent activity
4 hits · last 30 days
node
4
Resources