Website: formharvester.com
FormHarvester is an AI-assisted form intelligence engine. It navigates the open web autonomously - executing searches, parsing page structure, extracting contact signals, and interacting with forms at the browser level. Built on async browser with stealth fingerprinting, proxy rotation, and a pluggable captcha solver interface.
How to run
Desktop app
Download formharvester.exe
(built automatically on every release by .github/workflows/release-windows-exe.yml), then run it.
Everything is configured in the app: no files to edit.
Python
pip install "formharvester[gui]"
formharvester gui # desktop app
formharvester run # headless harvest loop
The [gui] extra pulls in pywebview. Plain pip install formharvester gives
you the CLI and the library without it.
Configuration
Settings live in formharvester.json, and each campaign (form-fill details plus
the search queries) lives in profiles/<name>.json. Run
formharvester settings path to see where they are stored. The location is the
working directory when a config already exists there, otherwise
~/.formharvester; FORMHARVESTER_HOME overrides both.
Scraped emails, progress files and error logs are written to data/ and
log/ inside that same directory.
From the GUI
formharvester gui opens three tabs: Run picks the active campaign and
streams the live console, Campaign edits the form-fill details and query
list, Settings covers the engine, search pacing and the captcha solver.
From the CLI
formharvester settings show # print current settings
formharvester settings set engine.headless true # values are validated
formharvester settings set google.max_pages 5
formharvester profile list
formharvester profile create solar
formharvester profile use solar
formharvester run --profile solar --headless --max-pages 5
formharvester discover "roofing companies austin" > targets.txt
Flags on run override the saved settings for that run only.
Settings reference
| Key | Meaning |
|---|---|
engine.send_form |
Submit the contact form once filled. Disable to save time. |
engine.headless |
Run the browser hidden. |
engine.skip_ads |
Skip ad results. |
engine.max_time |
Seconds allowed per website. |
engine.generate_email_sources |
Also record the URL each email came from. |
engine.debug_form |
Fill forms but never submit them. |
google.start_page |
Results page to start from. |
google.max_pages |
Result pages to walk per query. |
google.min_delay / google.max_delay |
Random delay range, in seconds, between searches. |
google.captcha_sleep |
Minutes to pause after a search captcha. 0 disables. |
google.search_timer |
Minutes between search batches. |
captcha.provider |
deathbycaptcha, 2captcha, none, or blank to auto-detect from the credentials you filled in. |
captcha.twocaptcha_api_key |
2captcha API key. |
captcha.dbc_username / captcha.dbc_password |
DeathByCaptcha credentials. |
Programmatic use (library API)
Since 2.4.0 FormHarvester ships a library API so you can drive the engine from
your own code - no settings files or progress files required. The CLI is
unchanged.
from formharvester import FormHarvester, FormFillDetails, HarvesterOptions
details = FormFillDetails(
first_name="Jane", last_name="Doe",
email="jane@example.com", phone="1234567890",
subject="Enquiry", message="Hi, I'd like a quote.",
)
with FormHarvester(details, HarvesterOptions(send_form=True, headless=True)) as fh:
result = fh.harvest("https://acme.com")
print(result.status, result.submitted, result.emails)
urls = fh.discover("roofing companies austin") # search -> site URLs
for r in fh.harvest_many(urls):
print(r.url, r.status)
result.status is one of SUBMITTED, FORM_NOT_FOUND, BUTTON_NOT_FOUND,
VISITED, or ERROR - the same tokens the CLI writes to its progress file.
One-shot helpers harvest_site(url, details) and harvest_sites(urls, details)
are also available.
discover() raises CaptchaError rather than blocking; set
HarvesterOptions.captcha_sleep to wait it out instead.
Package layout (2.4.1)
src/formharvester/
├── __init__.py # public API (FormHarvester, FormFillDetails, …)
├── api.py # library API
├── engine/ # Selenium browser engine + Chrome driver
├── scraper/ # web search + email scraping
├── form_handler/ # contact-page discovery, field fill, submit
├── captcha/ # solver providers (DeathByCaptcha, 2captcha) + detection
├── settings.py # JSON settings, profiles and file locations
├── cli/ # typer commands (`formharvester`)
├── gui/ # pywebview desktop app (web/ holds its HTML, CSS, JS)
└── utils/ # root-domain, email regex, link filters
Building the Windows executable (maintainers)
.github/workflows/release-windows-exe.yml builds formharvester.exe with PyInstaller and
attaches it to the GitHub Release for any pushed v* tag (also runnable manually via
workflow_dispatch). To build it locally:
uv sync --no-group dev --extra gui
uv pip install pyinstaller
uv run pyinstaller packaging/formharvester.spec
The executable launches the desktop app. The formharvester command installed
by pip is the CLI.
This project is released under the MIT License. You are free to use, modify, and distribute this software, provided that the original copyright notice and license terms are included in all copies or substantial portions of the software.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file formharvester-2.4.1.tar.gz.
File metadata
- Download URL: formharvester-2.4.1.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8c4be8ce4542124d6e11898d614e3feb981360e67f658518e994ddd805de505
|
|
| MD5 |
36ae6f64186cda1e598c39e839989012
|
|
| BLAKE2b-256 |
ac76b190499591284e81aaec25f4bc5232b669013897347024137a52947eb6c9
|
Provenance
The following attestation bundles were made for formharvester-2.4.1.tar.gz:
Publisher:
publish.yml on dariomory/formharvester
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formharvester-2.4.1.tar.gz -
Subject digest:
a8c4be8ce4542124d6e11898d614e3feb981360e67f658518e994ddd805de505 - Sigstore transparency entry: 2225379063
- Sigstore integration time:
-
Permalink:
dariomory/formharvester@9b998a2249f77bd76eb180d7526cab0f7de84594 -
Branch / Tag:
refs/tags/v2.4.1 - Owner: https://github.com/dariomory
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9b998a2249f77bd76eb180d7526cab0f7de84594 -
Trigger Event:
push
-
Statement type:
File details
Details for the file formharvester-2.4.1-py3-none-any.whl.
File metadata
- Download URL: formharvester-2.4.1-py3-none-any.whl
- Upload date:
- Size: 75.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4aeacdb4387482d9cdf42c31330633ab6c73d74e2ff0a910f9c673c4a4acb1bc
|
|
| MD5 |
11d7ddb4726e6354d92fd617f7a86965
|
|
| BLAKE2b-256 |
f5d512cd835cfd5e1bd740be097b9766a749251ddef9ff5315d86f4988b2fdf1
|
Provenance
The following attestation bundles were made for formharvester-2.4.1-py3-none-any.whl:
Publisher:
publish.yml on dariomory/formharvester
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formharvester-2.4.1-py3-none-any.whl -
Subject digest:
4aeacdb4387482d9cdf42c31330633ab6c73d74e2ff0a910f9c673c4a4acb1bc - Sigstore transparency entry: 2225379426
- Sigstore integration time:
-
Permalink:
dariomory/formharvester@9b998a2249f77bd76eb180d7526cab0f7de84594 -
Branch / Tag:
refs/tags/v2.4.1 - Owner: https://github.com/dariomory
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9b998a2249f77bd76eb180d7526cab0f7de84594 -
Trigger Event:
push
-
Statement type: