| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Using your own Microsoft Copilot account. No API key, no credits, no paid plan: it turns the free chat at copilot.microsoft.com into an API you can call from code.
You can use it in two ways:
You sign in once with your Microsoft account in a browser; your session is saved and refreshed automatically after that.
Unofficial project. Not affiliated with or endorsed by Microsoft. It automates the consumer Copilot web experience for personal use, so use it responsibly and within Microsoft's terms.
# 1. Clone the project
git clone <your-repo-url>
cd Windows-Copilot-API2. Create and activate a virtual environment
On macOS / Linux:
python3 -m venv venv
source venv/bin/activateOn Windows (PowerShell):
python -m venv venv
venv\Scripts\Activate.ps1On Windows you may need to allow script execution once: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned. In cmd.exe activate with venv\Scripts\activate.bat instead.
3. Install dependencies and sign in
# Install dependencies
pip install -r requirements.txt
# Install the browser Playwright needs (one-time)
playwright install chromium
# Sign in once: a browser opens, log into your Microsoft account
python -m copilot loginThat's it. Your session is saved under session/ (git-ignored, never shared) and reused on every run.
💡 You can even skip the login step: the first time you call chat() or start the server, it opens the sign-in browser for you automatically.
If you are on Windows, you can bypass the manual steps above and use our smart startup script:
.\start_service.ps1It automates the entire lifecycle:
Prefer a container? You can run the OpenAI-compatible server in Docker once you've signed in.
Sign in on the host first. The login step above opens a visible browser, which can't run inside the headless container — so run python -m copilot login on your host to populate session/. The container mounts that folder and only does the automatic (headless) token refresh from then on.
docker compose up --build
# -> Copilot OpenAI-compatible API on http://localhost:8000The docker-compose.yml maps port 8000 and bind-mounts your session/ so the login persists across restarts. Tune RATE_LIMIT_RPM / RATE_LIMIT_BURST there. To run without Compose, build and pass the same bindings by hand:
docker build -t windows-copilot-api .
docker run --rm -p 8000:8000 -v "$(pwd)/session:/app/session" windows-copilot-apiThe simplest way if your code is already Python.
from copilot import CopilotClient
client = CopilotClient() # loads your signed-in session
# Get a full reply
reply = client.chat("Say hello in one short sentence.")
print(reply.text)
# Continue the SAME conversation — pass the id back
reply2 = client.chat("And now in French?", reply.conversation_id)
print(reply2.text)
# Stream the answer as it's typed
for chunk in client.stream("Tell me a short joke"):
print(chunk, end="", flush=True)chat() returns the full text plus a conversation_id; pass that id back to keep the thread going, or omit it to start fresh. stream() yields the reply piece by piece.
👉 More: examples/01_direct_chat.py, 02_direct_conversation.py, 03_direct_stream.py
Start a local server that speaks the OpenAI API, so existing OpenAI tools and SDKs work unchanged.
python app.py
# -> Copilot OpenAI-compatible API on http://127.0.0.1:8000Then point any OpenAI client at it (the API key is required by the SDK but ignored):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="unused")
resp = client.chat.completions.create(
model="copilot-creative", # supports: copilot (balanced), copilot-creative (creative), copilot-precise (precise)
messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)Or call it with plain HTTP / curl:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "copilot-creative", "messages": [{"role": "user", "content": "Hello!"}]}'Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /v1/chat/completions | Chat (supports "stream": true and an optional "conversation_id") |
| GET | /v1/models | Lists the supported model variations: copilot, copilot-creative, and copilot-precise |
Change the address with env vars: HOST=0.0.0.0 PORT=8080 python app.py, or run uvicorn server.api:app --host 0.0.0.0 --port 8080.
👉 More: examples/04_server_http.py, 05_server_stream.py, 06_server_openai_sdk.py
python -m copilot login # sign in and save the session
python -m copilot ask "Hello!" # quick one-shot questionThe server bridges a single signed-in Copilot account, and Copilot's chat socket doesn't tolerate concurrent conversations from one process. So the server serializes upstream calls: parallel HTTP requests queue behind a lock and run one at a time (see server/api.py). This is intentional, and it means throughput is sequential, not parallel.
You can measure where it breaks with the included stress test, which fires a batch of simultaneous requests and doubles the batch size every successful round until the first error:
# Start the server in one terminal
python app.py
# Ramp concurrency in another (1 → 2 → 4 → 8 → …)
python tests/stress.py
python tests/stress.py --max 64 --timeout 120 --url http://localhost:8000Sample run (one signed-in account):
| Concurrency | Result | Wall time | Latency (min / median / max) |
|---|---|---|---|
| 1 | ✓ all ok | 3.7s | 3.7 / 3.7 / 3.7s |
| 2 | ✓ all ok | 4.6s | 3.4 / 4.6 / 4.6s |
| 4 | ✓ all ok | 8.3s | 3.7 / 6.7 / 8.3s |
| 8 | ✗ 1 failed (HTTP 502) | 13.3s | 3.5 / 9.7 / 13.3s |
Highest fully-successful concurrency: 4. Wall time roughly doubles each round while minimum latency stays flat (~3.5s) — the signature of a serialized queue: one request runs immediately, the rest wait their turn. The failure at 8 is an upstream 502 (Copilot rejecting requests under load), not a server crash or timeout — so the exact break point is flaky and may vary between runs.
Takeaway: keep concurrent in-flight requests low (≈ 1–4). This is a personal bridge, not a high-throughput gateway — and please don't hammer your account.
Concurrency (above) is how many at once; the rate limit is how many per minute, sustained. Microsoft publishes none for consumer Copilot, so the bridge enforces a self-imposed one with a token bucket: it caps accepted requests per minute and returns a standard 429 + Retry-After when you exceed it. Two env vars tune it:
| Env var | Default | Meaning |
|---|---|---|
| RATE_LIMIT_RPM | 12 | Requests/minute the bridge accepts. 0 disables the limit. |
| RATE_LIMIT_BURST | 4 | How many requests may go back-to-back before pacing kicks in. |
RATE_LIMIT_RPM=20 RATE_LIMIT_BURST=5 python app.py # raise it; 0 to disableThe default 12 rpm sits safely below the ~15 rpm where a single account starts seeing upstream 502s. To find your ceiling, run the server with the limiter off (RATE_LIMIT_RPM=0) and push the probe until failures appear:
python tests/ratelimit.py --rpm 20 --minutes 3On the client side, use exponential backoff. Both 429 (bridge limit) and the occasional 502 (Copilot upstream hiccup) are transient — retry with growing delays (e.g. 1s, 2s, 4s) and they almost always clear. The official openai SDK does this automatically and honours Retry-After; with plain HTTP, add a few retries yourself.
| Path | What it does |
|---|---|
| copilot/ | The core library: CopilotClient, auth, browser sign-in, HTTP driver |
| server/ | The FastAPI OpenAI-compatible server |
| examples/ | Runnable examples for every feature (examples/README.md) |
| tests/ | Test scripts, including the concurrency stress test (tests/stress.py) |
| app.py | Starts the server |
RuntimeError: Copilot error: invalid-event (or the chat hangs) on a server/VPS. On datacenter IPs Cloudflare withholds bot-clearance, so the chat socket stalls on an empty challenge sometimes. Fix it manually: on that machine, open copilot.microsoft.com in a browser and pass the "verify you're human" check once; that sets a cf_clearance cookie which the saved session reuses. Re-do it if it expires, or route the server's traffic through a residential connection (e.g. a home-PC exit node).
socks5h:// proxy and WebSocket connection failures (WinError 10061 / TLS connect error): Windows proxy clients may automatically configure socks5h:// in environmental variables. The library's underlying curl_cffi cannot resolve wss:// handshakes over socks5h directly. The bridge now automatically normalizes socks5h:// to socks5:// in its driver and browser module to prevent this failure.
UnicodeEncodeError: 'gbk' codec can't encode character... when printing replies on Windows console: When driving the API under the default Windows Command Prompt or PowerShell, printing replies that contain emoji characters (like 🍎) can trigger encoding errors and break the websocket thread. The driver now automatically configures standard I/O streams with robust replacement settings (sys.stdout.reconfigure(errors="replace")), making it fully immune to console encoding crashes.
For personal and educational use. You are responsible for complying with Microsoft's terms of service.
| Back | FazBrowse Home | New Git URL |