Skip to content

Repository files navigation

AnyAPI — Self-Hosted AI API Server

Python License: MIT Playwright GitHub Pages

Run a local API server that gives you free access to 9 AI providers — no API key, no billing, no rate-limit surprises. Build chatbots, CLIs, scripts, and automations on top of it.

AnyAPI is a self-hosted API server built on Playwright browser automation. Start the daemon once; it drives a real browser session and exposes a JSON-RPC socket API. Then call that API from any Python project, shell script, chatbot framework, or tool you're building. A full interactive REPL (anyapi) ships as a built-in client — but it's just one of many things you can wire to the API.

Legal notice: This tool automates web interfaces without using official APIs. Use may violate the Terms of Service of individual providers. It is intended for personal experimentation and research only. You are responsible for reviewing each provider's ToS before use. The authors accept no liability.


What you can build

  • Chatbots — a Telegram bot, a Discord bot, a Slack slash-command handler
  • CLI tools — a domain-specific shell assistant, a code-review tool, a doc generator
  • Automation scripts — summarise PRs, triage issues, generate commit messages
  • Agent pipelines — chain calls across providers, route by task type, compare outputs
  • REPL / playground — AnyAPI's built-in interactive shell (ships with the package)

All powered by the same free web UIs you already use — no billing setup required.


9 Providers. 5 Need Zero Setup.

Provider Free to use Setup
duckduckgo Nothing — start immediately
copilot Nothing — start immediately
huggingchat Nothing — start immediately
perplexity Nothing — start immediately
you Nothing — start immediately
deepseek Export cookies + localStorage (~5 min)
chatgpt Export cookies (~5 min)
gemini Export cookies (~5 min)
qwen Export cookies + localStorage (~5 min)

Installation

pip install anyapi
playwright install chromium   # one-time browser download (~150 MB)

Requires Python 3.10+ on Linux or macOS. WSL2 works great on Windows.

Install from source:

git clone https://github.com/dheeraj7000/anyapi
cd anyapi
pip install -e .
playwright install chromium

Quick Start

1 — Start the API server

anyapi-daemon --provider duckduckgo

The daemon launches Chromium, navigates to the provider, and listens on a Unix socket at ~/.local/share/anyapi/duckduckgo_daemon.sock. Leave it running.

2 — Call it from Python

import asyncio
from anyapi.cli.client import DaemonClient
from pathlib import Path

async def ask(prompt: str, provider: str = "duckduckgo") -> str:
    sock = Path.home() / f".local/share/anyapi/{provider}_daemon.sock"
    client = DaemonClient(sock)
    reply = []
    async for event in client.send_request("ask", {"prompt": prompt}):
        if event.event == "token":
            reply.append(event.data)
        elif event.event in ("done", "error"):
            break
    return "".join(reply)

# Summarise a file
answer = asyncio.run(ask("Summarise this: " + open("README.md").read()))
print(answer)

3 — Or use the built-in interactive REPL

anyapi --provider duckduckgo
AnyAPI — Duckduckgo · /help for commands

› What's the difference between async and parallel?
  Async is about waiting efficiently — one thread handles many tasks by
  yielding control while waiting for I/O. Parallel is about doing multiple
  things at the exact same time across multiple CPU cores...

› /save first-session
  Saved: first-session  (id=a3f8c1d2e4b5)

4 — Or pipe it as a Unix tool

anyapi --provider duckduckgo "Summarise: $(cat main.py)"
git diff HEAD~1 | anyapi --provider deepseek "Review this diff for bugs"
echo "What is 17 * 89?" | anyapi --provider duckduckgo

API Reference

The daemon accepts JSON-RPC requests over a Unix domain socket. Each request is a newline-delimited JSON object; the daemon streams back events until a done or error event closes the exchange.

Request format

{"id": "uuid", "method": "ask", "params": {"prompt": "Hello!"}}

Event stream format

{"id": "uuid", "event": "status", "data": {"stage": "typing"}}
{"id": "uuid", "event": "token",  "data": "Hello"}
{"id": "uuid", "event": "token",  "data": " there"}
{"id": "uuid", "event": "done",   "data": {"text": "Hello there", "chars": 11}}

Methods

Method Params Description
ask prompt: str Send a prompt; streams token events then done
new_chat Start a fresh browser conversation
save_conversation name?: str Save current conversation
load_conversation id: str Load a saved conversation (prefix match)
list_conversations List all saved conversations
current_conversation Get full turn history for active conversation
stats Rate-limit status and session info
health Browser and provider health check
reload_auth Re-inject cookies without restarting the daemon
shutdown Gracefully shut down the daemon

Python client — streaming example

import asyncio
from anyapi.cli.client import DaemonClient
from pathlib import Path

async def stream(prompt: str, provider: str = "duckduckgo"):
    sock = Path.home() / f".local/share/anyapi/{provider}_daemon.sock"
    client = DaemonClient(sock)
    async for event in client.send_request("ask", {"prompt": prompt}):
        if event.event == "token":
            print(event.data, end="", flush=True)
        elif event.event == "done":
            print()  # newline after response
            break
        elif event.event == "error":
            print(f"\nError: {event.data}")
            break

asyncio.run(stream("Write a haiku about Unix pipes"))

Chatbot example (Telegram-style pseudocode)

from anyapi.cli.client import DaemonClient
from pathlib import Path

class AIBot:
    def __init__(self, provider="deepseek"):
        sock = Path.home() / f".local/share/anyapi/{provider}_daemon.sock"
        self.client = DaemonClient(sock)

    async def reply(self, user_message: str) -> str:
        parts = []
        async for event in self.client.send_request("ask", {"prompt": user_message}):
            if event.event == "token":
                parts.append(event.data)
            elif event.event in ("done", "error"):
                break
        return "".join(parts)

bot = AIBot(provider="deepseek")

# In your Telegram/Discord/Slack handler:
# response = await bot.reply(message.text)
# await message.reply(response)

Credential Setup (for DeepSeek, ChatGPT, Gemini, Qwen)

AnyAPI reads credentials from:

~/.local/share/anyapi/providers/<provider>/cookies.json
~/.local/share/anyapi/providers/<provider>/localstorage.json   # deepseek, qwen only

Step-by-step

  1. Log in to the provider's website in your normal browser.
  2. Install the Cookie-Editor browser extension.
  3. Open the extension → Export → JSON format. Copy the output.
  4. Create the credentials directory and save the file:
mkdir -p ~/.local/share/anyapi/providers/deepseek
chmod 700 ~/.local/share/anyapi/providers/deepseek
nano ~/.local/share/anyapi/providers/deepseek/cookies.json   # paste here
  1. For DeepSeek and Qwen only — also export localStorage:
    • Open DevTools → Console
    • Run: copy(JSON.stringify(localStorage))
    • Save:
nano ~/.local/share/anyapi/providers/deepseek/localstorage.json
  1. Lock down permissions:
chmod 600 ~/.local/share/anyapi/providers/deepseek/*.json
  1. Start and verify:
anyapi-daemon --provider deepseek
anyapi --provider deepseek
› /health

Daemon Reference

# Start (foreground — use tmux/screen or systemd to background it)
anyapi-daemon --provider duckduckgo

# Watch the browser (useful for first-run auth)
anyapi-daemon --provider deepseek --headed

# Verbose logging
anyapi-daemon --provider duckduckgo --verbose

# Custom state directory
anyapi-daemon --provider chatgpt --base-dir /path/to/dir

Run as a systemd service (background daemon)

# ~/.config/systemd/user/anyapi-duckduckgo.service
[Unit]
Description=AnyAPI daemon — duckduckgo

[Service]
ExecStart=%h/.local/bin/anyapi-daemon --provider duckduckgo
Restart=on-failure

[Install]
WantedBy=default.target
systemctl --user enable --now anyapi-duckduckgo

Built-in CLI Client Reference

REPL slash commands

Command Description
/help Show all commands
/new Start a new conversation
/list List saved conversations
/load <id> Load by 12-char prefix from /list
/save [title] Save current conversation
/file <path> Stage a file to inline into your next prompt
/auth Show credential setup instructions
/stats Rate-limit and session info
/health Daemon and browser health check
/clear Clear screen
/exit or /quit Exit

Inline files with @path

› Explain this: @src/main.py
› What's wrong with @tests/test_auth.py?
› Review all: @src/**/*.py

Docker / Container Usage

Chromium requires --no-sandbox without user namespaces:

export ANYCLI_NO_SANDBOX=1
anyapi-daemon --provider duckduckgo

Architecture

  Your code / chatbot / script
         │
         │  import DaemonClient
         │  send_request("ask", {"prompt": "..."})
         ▼
  Unix socket  (~/.local/share/anyapi/<provider>_daemon.sock)
         │
         ▼
  anyapi-daemon  (API server)
  ┌─────────────────────────────────────────┐
  │  Playwright · Chromium browser          │
  │  Rate limiter (bucket + burst cap)      │
  │  Conversation manager (save/load)       │
  │  Provider plugins: deepseek, chatgpt …  │
  └─────────────────────────────────────────┘

  anyapi  (built-in reference client)
  ┌─────────────────────────────────────────┐
  │  Interactive REPL (prompt_toolkit)      │
  │  One-shot mode (stdin pipe)             │
  │  Rich streaming renderer                │
  └─────────────────────────────────────────┘

The daemon and CLI are decoupled. Multiple clients can share one daemon. You can replace anyapi entirely with your own client — the socket protocol is stable.


Limitations

  • Selector fragility — Providers use DOM selectors that break when sites update. Open an issue if one stops working.
  • No true streaming — Responses arrive after the AI finishes generating (stability polling), not token-by-token in real time.
  • Rate limits — AnyAPI applies local caps (60 req/hour, 300/day) to avoid triggering provider-side blocks.
  • Browser context — Conversation history lives in the browser tab; /load restores turn history and navigates to the saved URL, but the exact browser context may differ after a daemon restart.
  • Terms of Service — Browser automation likely violates each provider's ToS. Use responsibly.

Contributing

See CONTRIBUTING.md for dev setup, adding providers, and PR guidelines.

pip install -e ".[dev]"
playwright install chromium
python -m pytest tests/

License

MIT — see LICENSE.

About

Self-hosted AI API server — free access to 9 providers via browser automation. Build chatbots, CLIs, and agents without API keys.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages