Alpaca vs IBKR API: REST keys vs the TWS socket
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.
Alpaca and Interactive Brokers both let you trade stocks from code, with paper accounts to test against. The choice is hard because their APIs are not two versions of one design. Alpaca is an HTTPS API you call with a key; IBKR’s TWS API is a socket to a desktop application a human has logged into. Almost every other difference follows from that.
This page is for developers choosing one or adding the second. It covers mechanism only — no commissions, no quotas — and does not recommend a broker. Account eligibility differs by country; check each broker’s own pages.
Short answer
- You want to run on a server with nothing else installed → Alpaca. The TWS API needs TWS or IB Gateway running and logged in.
- You want API orders blocked until you deliberately allow them → IBKR’s Read-Only API setting is on by default. On Alpaca, a read-only key is available, but you choose it at creation.
- You want official SDKs from a package manager → Alpaca publishes its SDKs as normal packages. IBKR distributes its official client only through its own installer.
- Your design is event-driven over one long-lived connection → the TWS API delivers everything, errors included, through callbacks on one socket.
What they have in common
- A paper environment that runs the same API as live, so the same code can target either.
- Official clients in Python, Java and C#/.NET.
- A read-only option — at key level on Alpaca, at application level on IBKR.
- A documented throttling mechanism, with the actual figure kept on the broker’s own page.
Where they actually differ
Transport and architecture
| Alpaca Trading API | IBKR TWS API | |
|---|---|---|
| Shape | HTTPS REST, plus WebSocket and SSE streams | TCP socket to a local TWS or IB Gateway |
| Hosts | api.alpaca.markets, paper-api.alpaca.markets, data.alpaca.markets | 127.0.0.1 (same machine) on the configured socket port |
| Request/response | Request and response per call, under /v2 | Requests through EClient, responses through EWrapper callbacks |
| Needs running | Nothing | TWS or IB Gateway, logged in |
IBKR also has a separate product, the Client Portal Web API: REST against
a local gateway at https://localhost:5000, needing Java and a funded IBKR Pro
account, re-authenticated in a browser daily, with no supported automated
authentication. Code for it does not port to the TWS API, which is what the
rest of this page compares. See
IBKR TWS API setup and
WebSocket vs REST for trading.
Authentication
Alpaca sends a key ID and secret in two headers, APCA-API-KEY-ID and
APCA-API-SECRET-KEY, or as HTTP Basic credentials. There is no request
signature, so signature construction and clock skew are simply not failure
modes. Alpaca now labels this the “Legacy” flow; its OAuth client-credentials
flow is not yet available for the Trading API. The secret is shown once, at
creation.
IBKR’s TWS API has no API key. A human logs into TWS or IB Gateway; your
program opens a socket to it. By default TWS asks for confirmation before
accepting an API connection, denies untrusted remote IPs without prompting, and
can be set to auto-accept trusted IPs. Each client identifies itself with a
client ID — up to 32 can connect to one session — and reusing an ID in use
returns 326 “Unable to connect as the client id is already in use.”
Paper trading
Alpaca puts paper on its own host, paper-api.alpaca.markets, with its own
keys and the same API spec, though some endpoints, such as Locates, are
unavailable in paper. A paper key on the live host fails with 401 or 403 —
Alpaca names both.
IBKR makes paper a separate login. The paper session listens on its own
port: by default 7497 for TWS and 4002 for IB Gateway, against 7496 and 4001
for live. The defaults can be changed, and your connect() call must match the
configured port.
Either way, the risk is pointing tested code at live by changing one value — a host on Alpaca, a port on IBKR. See the Alpaca paper trading API and what paper trading is.
Permissions and safe defaults
Alpaca scopes the key at creation through Access Controls: Read only,
Full access, or Custom, with Read & Write or Read only per scope. Keys
can also be given an expiry. For OAuth apps, leaving out the trading and
account:write scopes yields a read-only integration.
IBKR has an application-level switch. The Read-Only API setting, under Global Configuration → API → Settings, is enabled by default and blocks all API orders until unchecked. The same panel holds “Enable ActiveX and Socket Clients”, which must be on for socket connections.
IBKR is where doing nothing gives you the safe configuration; on Alpaca
the safe configuration is a choice you make when you create the key. Users
report error 321 with the text “The API interface is currently in Read-Only
mode”; IBKR’s own table lists 321 only as a generic validation error. See
read-only vs trade permission.
Rate-limit mechanism
Alpaca uses a per-minute request window and reports it on responses:
X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (the Unix
time the quota changes). Exceeding it returns 429.
IBKR’s TWS API caps the rate of messages per second from client to TWS.
Exceeding it produces error 100 “Max rate of messages per second has been
exceeded.”, and IBKR notes TWS will likely disconnect the client. The Client
Portal Web API is different again: 10 requests per second per authenticated
username, 429 on breach.
The practical difference is what a breach costs. On Alpaca you get a 429 and
headers to pace by; on the TWS API you may lose the connection. See
rate-limit models compared.
Official SDKs
Alpaca provides and supports alpaca-py (Python), Alpaca.Markets
(.NET), @alpacahq/alpaca-trade-api (Node), alpaca-trade-api-go and
alpaca-java, and publishes OpenAPI specs for client generation. Rust and
other wrappers are listed separately as community-made.
IBKR ships Python, Java, C++, C# and VB.NET clients, plus Excel
integrations, only through its own MSI or ZIP installer. IBKR states that
packages on pip, NuGet or other online repositories are not hosted, endorsed or
supported by it, and recommends keeping the API version in step with TWS.
Popular wrappers such as ib_insync and ib_async are third-party; a reply on
an IBKR Campus lesson says IBKR does not support ib_insync.
How errors reach your code
Alpaca errors come back on the request that caused them: an HTTP status and
a JSON body with code and message, for example 42210000 with a sub-penny
limit_price message. 403 is overloaded — on POST /v2/orders it means
buying power or shares are insufficient, wash-trade protection also returns it,
and Alpaca says invalid credentials can sometimes produce 403 instead of
401.
IBKR delivers errors asynchronously through EWrapper.error(), with the
originating request ID (or order ID), a numeric code and a description. The
same callback carries warnings and informational messages: 2104 “Market data
farm connection is OK” arrives on every healthy connect. And 502 “Couldn’t
connect to TWS” is raised by the operating system on the client side, so it
never appears in TWS’s logs.
An Alpaca client handles errors inline; an IBKR client needs a dispatcher that correlates by request ID and filters informational codes. See auth errors across exchanges.
Which to pick
| Your situation | Lean toward | Why |
|---|---|---|
| Headless deployment, nothing else running | Alpaca | Plain HTTPS; the TWS API needs a logged-in desktop app |
| You want orders blocked by default | IBKR | Read-Only API is on until you turn it off |
| You want per-scope key permissions | Alpaca | Custom Access Controls per scope |
| You install dependencies from pip/npm/NuGet | Alpaca | IBKR’s official client comes only from its installer |
| You want one persistent, callback-driven connection | IBKR | EClient out, EWrapper in |
| You want unattended REST access at IBKR | Plan for a human step | The Client Portal Web API needs daily re-authentication |
Can you use both
Yes, behind a thin common interface — submit order, get positions, get account. Do not share error handling (synchronous HTTP vs an asynchronous callback stream), and keep paper and live as separate configuration slots on both: one wrong host or port is all it takes.
FAQ
Does IBKR have API keys like Alpaca?
Not for the TWS API. A person logs into TWS or IB Gateway, and your program connects to it over a local socket, identified by a client ID. Alpaca uses a key ID and secret in request headers, with no desktop application involved.
Why are my API orders rejected on a fresh IBKR install?
Often it is the Read-Only API setting, which IBKR enables by default and which
blocks all API orders. Uncheck it under Global Configuration
→ API → Settings. Users report error 321 with “The API interface is currently
in Read-Only mode” when this happens.
Is ib_insync the official IBKR Python API?
No. IBKR distributes its official Python client only through its own installer
and says packages on pip and other repositories are not hosted, endorsed or
supported by it. ib_insync and ib_async are third-party wrappers around the
TWS API.
How do Alpaca and IBKR paper trading differ?
Alpaca paper runs on a separate host, paper-api.alpaca.markets, with separate
keys and the same API spec. IBKR paper is a separate login to TWS or IB
Gateway, listening by default on port 7497 (TWS) or 4002 (Gateway) instead of
the live 7496 or 4001.