September 23, 2026 · 4 min read

iMessage API Python: send and receive without a Mac

Give your Python AI agent a messaging line. This example sends one message and waits for your matching reply.

One connection, both directions
Python agentSend a unique test codeReceive the matching reply
Your test phoneOpen the new messageReply with that code

Choose the right Python approach

Claw Messenger is a managed API for AI agents. Your Python process can run on Linux, Windows, or macOS.

You don't need to run a Mac server. It does not read your personal iMessage history or use your personal Apple account.

For scripts running through your own Mac, py-iMessage documents a different, Mac-only approach.

Prepare one controlled test

Use Python 3.11 or later and an active Claw Messenger account. The seven-day trial requires a card.

In your dashboard, register a phone you control and create an API key. Use its full international number, including the plus sign.

Set CLAW_API_KEY and CLAW_TEST_PHONE in your server environment. Keep the key out of source control and browser code.

python -m pip install "websockets>=13,<17"

Send and receive in one Python script

Save this as first_reply.py, then run python first_reply.py. Reply to the received message with its exact test code.

import asyncio
import json
import os
import secrets
from websockets.asyncio.client import connect

async def main():
    key = os.environ["CLAW_API_KEY"]
    phone = os.environ["CLAW_TEST_PHONE"]
    token = secrets.token_hex(4)
    async with connect(
        "wss://claw-messenger.onrender.com/ws",
        additional_headers={"Authorization": f"Bearer {key}"},
        open_timeout=15,
    ) as ws:
        await ws.send(json.dumps({
            "type": "send", "id": token, "to": phone,
            "parts": [{"type": "text", "value": f"Reply with {token}"}],
        }))
        async with asyncio.timeout(180):
            while True:
                event = json.loads(await ws.recv())
                kind = event.get("type")
                if kind == "ping":
                    await ws.send(json.dumps({"type": "pong"}))
                elif kind == "error":
                    raise RuntimeError(event.get("code", "API error"))
                elif kind == "send.result" and event.get("id") == token:
                    if not event.get("ok"):
                        raise RuntimeError(event.get("error") or "Send failed")
                    print("Send accepted. Reply from your test phone.")
                elif (
                    kind == "message"
                    and event.get("from") == phone
                    and (event.get("text") or "").strip() == token
                ):
                    print("Matching reply reached Python.")
                    return

try:
    asyncio.run(main())
except TimeoutError:
    print("Connection or reply wait timed out. No reply was proved.")

The Authorization header authenticates the socket without placing your key in the URL. The script answers server pings while waiting.

A fresh code prevents an old message from passing this test. Success means your reply reached Python, not just the phone.

What each result means

Send accepted
The API accepted your request; a reply is still needed.
Matching reply
Your test phone's code reached this process.
Timeout
No matching reply arrived during this test.

If connection fails, check the key and account status. If sending fails, check your message allowance and recipient limits.

If the phone receives nothing, check delivery status before retrying. Accepted, delivered, and read are separate states.

Routing can use iMessage, RCS, or SMS. A successful send alone does not prove iMessage delivery.

Move from a test to a client agent

This script exits after one reply. Production needs a persistent listener, reconnect backoff, and duplicate-message handling.

REST sends are also available, but self-serve replies still return over WebSocket. A short-lived HTTP function cannot keep that listener alive.

For separate client workspaces, use Agency subtenants. Each has a dedicated visible number; one line can serve many users.

Keep API keys and message routing separate for each client. Agency reviews your use case before setup.

Plan your Agency setup

Try Claw Messenger free for 7 daysiMessage API for AI agents. No Mac required.