Metadata-Version: 2.4
Name: morfiade
Version: 0.1.0
Summary: Python client for the Morfiade local API — script local Chrome profiles on Windows
Author-email: Morfiade <github@morfiade.com>
License-Expression: MIT
Project-URL: Homepage, https://morfiade.com/en/
Project-URL: Repository, https://github.com/morfiade-app/morfiade-python
Project-URL: Documentation, https://github.com/morfiade-app/morfiade-python#readme
Keywords: chrome,profiles,multi-account,browser-automation,playwright,cdp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# morfiade

**Python client for the [Morfiade](https://morfiade.com/en/) local API.** Script
real Chrome profiles on your own Windows machine — list, create, launch, stop,
set proxies, attach Playwright — each profile with its own cookies, sessions and
proxy.

```python
from morfiade import Morfiade

api = Morfiade()                         # address and token are found automatically
for p in api.profiles():
    print(p["name"], "running" if p["running"] else "stopped", p["proxy"])

info = api.start("shop-1", url="https://example.com/")
print(info["ws"])                         # DevTools address for Playwright / Puppeteer
```

One file, standard library only, Python 3.7+. Русская версия —
[README.ru.md](README.ru.md).

---

## Install

```
pip install morfiade
```

## Requirements

- Windows 10 or 11
- [Morfiade](https://morfiade.com/en/) 3.36 or newer, **running**
- **Local API enabled** in its settings
- The **"API" checkbox ticked** on the profiles a script may touch; unticked
  profiles do not exist as far as the API is concerned. Profiles created through
  the API are ticked automatically
- A valid licence to *launch* profiles (the check lives in the program)

## Where the token comes from

Nothing to copy by hand in the usual case. First match wins:

1. `Morfiade(url=..., token=...)`;
2. `MPC_API_URL` / `MPC_API_TOKEN` — Morfiade sets them for scripts it runs from
   its own **Scripts** tab, so those need no setup;
3. `MORFIADE_API_URL` / `MORFIADE_API_TOKEN`;
4. Morfiade's `config.json` for the current Windows user (`MORFIADE_CONFIG`
   points at another one). The token is stored there encrypted with Windows
   DPAPI and can be decrypted only under the same Windows account.

## Two ways to drive a profile

`start()` tells you which one applies:

| `transport` | What you get | Use it with |
|---|---|---|
| `"port"` | `ws` — a DevTools address | `playwright.chromium.connect_over_cdp(ws)`, `puppeteer.connect` — see [examples/playwright_attach.py](examples/playwright_attach.py) |
| `"extension"` | no address, on purpose | `api.cdp(...)` and `api.evaluate(...)` — see [examples/extension_cdp.py](examples/extension_cdp.py) |
| `"none"` | the window only | nothing — tick a checkbox below and restart the profile |

Which one a profile gets is set by two checkboxes in Morfiade: **Debug mode**
gives it a port, **antidetect** without debug mode gives it the extension. A
profile with neither — a freshly created one, for instance — starts with no
control channel at all: the window opens, and `start()` says `"none"` (Morfiade
3.37 and older fail instead, after a 20-second wait). Tick Debug mode on
profiles you want to open in Playwright.

Why the second one exists: a debugging port on Chrome's command line is enough
for Google to refuse sign-in, whatever else you do. Profiles that need a Google
account run without it, and Morfiade passes CDP commands through its own
extension instead.

## Methods

**Program:** `ping()`, `status()`

**Profiles:** `profiles()`, `profile(name)`, `start(profile, url=None)`,
`stop(profile)`, `session(profile)`, `create_profile(name, proxy=None,
proxy_type="http", category=None, note=None, note_title=None)`

**Recycle bin:** `trash(profile)`, `trash_list()`, `restore(profile)` — and
`delete_profile(profile)`, which deletes for good after a zip backup. Emptying
the bin is not in the API at all: that stays with a human.

**Proxy, tags, notes:** `set_proxy(profile, proxy, proxy_type="http")`,
`check_proxy(profile=None, proxy=None, proxy_type="http")`,
`tags(profile, tags=None)`, `note(profile, note=None, title=None)`

**Running profile:** `cdp(profile, method, params=None, tab=None)`,
`evaluate(profile, expression, tab=None)`

**Scripts:** `scripts()`, `run_script(script, profiles=None, timeout=120)`

**Window synchronizer:** `sync_windows()`, `sync_sets(name=None, lines=None)`,
`sync_spread(set_name, profiles=None)`, `sync_insert(set_name, leader=None)`

Anything newer than this client: `api.call("/route", {...})`.

Proxy passwords never come back from the API — `profiles()` shows them masked —
and value sets come back as counts, not values.

## Errors

A refusal raises `MorfiadeError` carrying the program's own reason, so there are
no `ok` fields to check. Subclasses tell the common cases apart:

| Exception | Meaning |
|---|---|
| `NotRunning` | nothing on the address: Morfiade is closed or its API is off |
| `Unauthorized` | the token was reissued in Morfiade's settings |
| `UnknownRoute` | the installed Morfiade is older than this call — update it |

Reasons come from the program and follow its interface language, so the wording
may be your own.

## Command line

```
morfiade status
morfiade profiles
morfiade start shop-1 https://example.com/
morfiade stop shop-1
```

## See also

- [morfiade-mcp](https://github.com/morfiade-app/morfiade-mcp) — the same
  program for AI agents over MCP
- [Manual](https://morfiade.com/en/manual/) — the local API section

## License

MIT for everything in this repository — see [LICENSE](LICENSE). Morfiade itself
is a separate commercial product with its own terms.
