manifest-api
Stop guessing selectors. Manifest tells your agent what's clickable, fillable, and submittable on any page.
Python SDK for the Manifest API — extracts structured action manifests from web pages so AI agents know what they can do, not just what's on screen.
| Raw browser access | Content extraction | Manifest | |
|---|---|---|---|
| Gives agents a browser | ✓ | ✗ | ✓ |
| Returns page content | ✓ | ✓ | ✓ |
| Returns available actions | ✗ | ✗ | ✓ |
| Required fields, input types | ✗ | ✗ | ✓ |
| Survives UI redesigns | ✗ | ✓ | ✓ |
Install
pip install manifest-api
Quickstart
Sync
from manifest_api import ManifestClient
client = ManifestClient(api_key="your-key") # or set MANIFEST_API_KEY env var
manifest = client.get("https://example.com")
print(manifest.current_page_state)
print(manifest.actions)
# Convenience helpers
action = manifest.action("submit-form")
inputs = manifest.actions_of_type("input")
required = manifest.required_actions
# Cheap structural-change check (no LLM call, never cached)
fp = client.fingerprint("https://example.com")
print(fp.fingerprint)
Async
import asyncio
from manifest_api import AsyncManifestClient
async def main():
async with AsyncManifestClient(api_key="your-key") as client:
manifest = await client.get("https://example.com")
print(manifest.current_page_state)
asyncio.run(main())
LangChain
pip install "manifest-api[langchain]"
from manifest_api.integrations.langchain import create_manifest_tool
tool = create_manifest_tool() # reads MANIFEST_API_KEY from env
# or: create_manifest_tool(api_key="...")
# use with an agent, e.g.:
from langchain.agents import create_agent
agent = create_agent(model=..., tools=[tool])
create_manifest_tool wraps AsyncManifestClient as a get_manifest(url) StructuredTool — the API key is bound at creation time, so the LLM never sees it.
All methods
# Both ManifestClient and AsyncManifestClient expose:
manifest = client.get("https://example.com") # POST /manifest → Manifest
manifest = client.get("https://example.com", country="US") # POST /manifest → Manifest, Accept-Language: en-US,en;q=0.9
fp = client.fingerprint("https://example.com") # POST /fingerprint → Fingerprint
health = client.health() # GET /health → dict
valid = client.session_valid() # GET /session-status → bool
Manifest helpers
manifest.action("id") # → Action | None
manifest.actions_of_type("input") # → list[Action]
manifest.required_actions # → list[Action]
manifest.blocked_actions([...]) # → list[Action], see "Action dependencies" below
manifest.fingerprint # → str | None, same hash `fingerprint()` returns
Fingerprint
fingerprint(url) runs the same page-render + extraction pipeline as
get(url) but skips the LLM translation step, returning just a stable hash
of the page's interactive surface (Fingerprint.fingerprint). Useful for
cheaply polling whether a page's action surface has changed since your last
get() call, without paying for another manifest generation. Every Manifest
also carries this same hash on manifest.fingerprint, so you can compare it
against a later fingerprint() call directly.
fp = client.fingerprint("https://example.com")
print(fp.url, fp.fingerprint)
Geo/locale
manifest = client.get("https://example.com", country="US") # ISO 3166-1 alpha-2
print(manifest.requested_country, manifest.served_locale, manifest.locale_mismatch)
country sets the scan's Accept-Language header to steer server-side
geo/locale redirects (e.g. a store redirecting to a different country's
pricing). This is a first attempt, not a guarantee — some sites geo-route on
IP and ignore Accept-Language entirely, no proxy routing yet. Check
manifest.locale_mismatch: True means a country was requested and the
page actually captured (manifest.served_locale, best-effort from the URL)
didn't match — an honest flag, not corrected pricing/currency data.
Action dependencies
Some actions are disabled until others are completed (e.g. a submit button
gated on required fields). Action.requires lists the ids of actions that
must be completed first; blocked_actions() filters a manifest down to
actions not yet unblocked by a given set of completed ids:
completed = ["email-input"]
still_blocked = manifest.blocked_actions(completed) # actions still waiting on something
requires is inferred by the LLM translation step from DOM signals (disabled
attributes, aria-disabled, form field proximity) — it's best-effort, not a
guaranteed-accurate dependency graph, and won't capture custom JS validation
logic.
Action types
button · input · textarea · select · checkbox · radio · other
Locators
Each action may carry a locator with css, role, and name — enough to
find and act on the underlying element without guessing a selector yourself.
It's best-effort: locator is None if no element on the page plausibly
matched the action.
Prefer role/name over css where possible — they hold up better across
redesigns, since css can be a brittle positional fallback when the element
has no id or name attribute.
action = manifest.action("continue")
if action.locator and action.locator.css:
page.click(action.locator.css)
Error handling
from manifest_api import AuthenticationError, RateLimitError, APIError
try:
manifest = client.get("https://example.com")
except AuthenticationError:
print("Check your API key")
except RateLimitError:
print("Slow down — rate limit hit")
except APIError as e:
print(f"Server error {e.status_code}")
Docs
Metadata
Release files for manifest-api 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| manifest_api-0.3.0.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| manifest_api-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.1 kB
Release files / manifest_api-0.3.0.tar.gz
| Download URL | manifest_api-0.3.0.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fde93635c0403fc9e24dca30cf3e9d41db8e6764373844f7c8a4a7bdecd0e211
|
|
BLAKE2b-256 checksum How to use checksums |
833f763203b3d37c1101b6884e544187433acc90053f2c45deeeda3e6bcad931
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|
Release files / manifest_api-0.3.0-py3-none-any.whl
| Download URL | manifest_api-0.3.0-py3-none-any.whl |
|---|---|
| Size | 8.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74767f1cece8de6387d72ce39518d87d53dc0a27b39946ef3b6505c3f54c1b83
|
|
BLAKE2b-256 checksum How to use checksums |
96f61677979ba78c6128a31e70c7b1bf1157be6518af09e748d58f10d20b910e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|