◈   ⌘ api · Intermediate

Kraken API Limits: What Every Trader Needs to Know

A practical guide to Kraken API rate limits, order types, and authentication for algo traders building bots or automating crypto strategies.

Uncle Solieditor · voc · 06.03.2026 ·views 88
◈   Contents
  1. → How Kraken API Rate Limits Work
  2. → Kraken API Limit Orders: Placing and Managing Them
  3. → Authentication Setup and Private Endpoint Access
  4. → Handling Rate Limit Errors and Building Resilient Bots
  5. → Kraken Pro API Limits and Upgrading Your Tier
  6. → Frequently Asked Questions
  7. → Building a Sustainable Kraken API Strategy

If you've built a trading bot on Kraken and suddenly started seeing 429 errors or EAPI:Rate limit exceeded messages, you've hit the API rate limit wall. It happens to everyone — usually at the worst possible moment, right when volatility spikes and your bot needs to fire orders fast. Understanding how Kraken's rate limiting system actually works is the difference between a bot that survives a volatile market and one that goes silent exactly when you need it most.

How Kraken API Rate Limits Work

Kraken uses a token bucket system for its REST API rate limits — not a simple requests-per-second counter. Each API key has a counter that starts at a maximum value and decays over time. Every request costs a certain number of tokens, and if your counter hits zero, requests start failing. The counter regenerates at a fixed rate, so sustained traffic is manageable as long as you don't burst too hard.

For the Kraken REST API, the limits differ based on your account tier. The base tier starts with a counter maximum of 15, with a decay rate of 0.33 per second. Intermediate tier bumps that to a max of 20 with 0.5/second decay. Pro and higher tiers get a max of 20 with a 1/second decay. That might not sound like a lot compared to what Binance offers on its spot API, but Kraken's system is designed for reliability over raw throughput.

Kraken API Rate Limits by Account Tier
TierCounter MaxDecay RateEffective RPS
Starter150.33/sec~0.33 req/sec sustained
Intermediate200.5/sec~0.5 req/sec sustained
Pro201/sec~1 req/sec sustained
Different endpoints cost different token amounts. A simple ticker call costs 1 token, while placing or canceling orders costs 0 tokens on the trading endpoints — but private endpoints like querying open orders cost 1 token each call. Always check the Kraken API docs for the specific cost of each endpoint you use.

Kraken API Limit Orders: Placing and Managing Them

A Kraken API limit order lets you specify the exact price at which you want to buy or sell. Unlike market orders, limit orders sit in the order book until they're filled or you cancel them. Through the API, you submit them to the AddOrder endpoint with ordertype set to limit. You can stack additional flags like post-only (to ensure maker fees) or reduce-only for futures positions.

import krakenex
import time
import hmac
import hashlib
import base64
import urllib.parse

# Initialize the Kraken API client
api = krakenex.API()
api.key = 'YOUR_API_KEY'
api.secret = 'YOUR_API_SECRET'

def place_limit_order(pair, side, volume, price):
    """
    Place a limit order on Kraken.
    pair: e.g. 'XBTUSD'
    side: 'buy' or 'sell'
    volume: string, e.g. '0.01'
    price: string, e.g. '65000'
    """
    params = {
        'pair': pair,
        'type': side,
        'ordertype': 'limit',
        'price': str(price),
        'volume': str(volume),
        'oflags': 'post'  # post-only to ensure maker fee
    }

    try:
        response = api.query_private('AddOrder', params)
        if response.get('error'):
            print(f'Order error: {response["error"]}')
            return None
        txid = response['result']['txid'][0]
        print(f'Order placed: {txid}')
        return txid
    except Exception as e:
        print(f'Exception placing order: {e}')
        return None

# Example: buy 0.01 BTC at $65,000
txid = place_limit_order('XBTUSD', 'buy', '0.01', '65000')

One thing that trips up developers coming from Binance or Bybit: Kraken uses its own asset pair naming convention. Bitcoin/USD is XBTUSD, not BTCUSDT. ETH/USD is ETHUSD. Always query the AssetPairs endpoint first if you're building something that needs to handle multiple symbols dynamically.

Authentication Setup and Private Endpoint Access

Kraken uses HMAC-SHA512 for API authentication. Every private request needs a nonce (incrementing integer) and a signature generated from the endpoint path plus the request payload. Getting this wrong is one of the most common reasons new bots fail silently — the auth error comes back as a generic EAPI:Invalid key message.

import urllib.parse
import hashlib
import hmac
import base64
import time
import requests

API_KEY = 'YOUR_API_KEY'
API_SECRET = 'YOUR_API_SECRET'
API_URL = 'https://api.kraken.com'

def get_kraken_signature(url_path, data, secret):
    postdata = urllib.parse.urlencode(data)
    encoded = (str(data['nonce']) + postdata).encode()
    message = url_path.encode() + hashlib.sha256(encoded).digest()
    mac = hmac.new(base64.b64decode(secret), message, hashlib.sha512)
    return base64.b64encode(mac.digest()).decode()

def kraken_request(uri_path, data):
    data['nonce'] = str(int(1000 * time.time()))
    headers = {
        'API-Key': API_KEY,
        'API-Sign': get_kraken_signature(uri_path, data, API_SECRET)
    }
    response = requests.post(
        API_URL + uri_path,
        headers=headers,
        data=data,
        timeout=10
    )
    return response.json()

# Fetch open orders
result = kraken_request('/0/private/OpenOrders', {'trades': True})
if result.get('error'):
    print('API Error:', result['error'])
else:
    orders = result['result']['open']
    print(f'Open orders count: {len(orders)}')
    for txid, order in orders.items():
        print(f'{txid}: {order["descr"]["order"]}')
Always store your API keys in environment variables, never hardcoded in source files. Rotate keys immediately if a repo with hardcoded credentials gets pushed to GitHub — Kraken's key management panel lets you create and revoke keys instantly.

Handling Rate Limit Errors and Building Resilient Bots

The most professional approach to Kraken API rate limits isn't trying to stay under the limit — it's building a system that handles the EAPI:Rate limit exceeded error gracefully and recovers without human intervention. On platforms like Bybit and OKX, WebSocket connections reduce the need to poll REST endpoints repeatedly. Kraken offers WebSockets too, and for live price data or order book updates, you should absolutely use them instead of hammering the REST API.

import time
import requests
from functools import wraps

class KrakenRateLimiter:
    def __init__(self, tier='starter'):
        tiers = {
            'starter': {'max': 15, 'decay': 0.33},
            'intermediate': {'max': 20, 'decay': 0.5},
            'pro': {'max': 20, 'decay': 1.0}
        }
        self.config = tiers.get(tier, tiers['starter'])
        self.counter = self.config['max']
        self.last_check = time.time()

    def _update_counter(self):
        now = time.time()
        elapsed = now - self.last_check
        self.counter = min(
            self.config['max'],
            self.counter + elapsed * self.config['decay']
        )
        self.last_check = now

    def can_request(self, cost=1):
        self._update_counter()
        if self.counter >= cost:
            self.counter -= cost
            return True
        return False

    def wait_and_request(self, cost=1):
        while not self.can_request(cost):
            time.sleep(0.1)

def with_retry(max_retries=3, backoff=2.0):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                result = func(*args, **kwargs)
                if isinstance(result, dict) and result.get('error'):
                    errors = result['error']
                    if any('Rate limit' in e for e in errors):
                        wait = backoff ** attempt
                        print(f'Rate limited. Waiting {wait}s...')
                        time.sleep(wait)
                        continue
                    # Non-rate-limit errors: don't retry
                    return result
                return result
            return result
        return wrapper
    return decorator

# Usage
rate_limiter = KrakenRateLimiter(tier='intermediate')

@with_retry(max_retries=3, backoff=2.0)
def safe_get_ticker(pair):
    rate_limiter.wait_and_request(cost=1)
    response = requests.get(
        f'https://api.kraken.com/0/public/Ticker?pair={pair}',
        timeout=5
    )
    return response.json()

ticker = safe_get_ticker('XBTUSD')
if not ticker.get('error'):
    last_price = ticker['result']['XXBTZUSD']['c'][0]
    print(f'BTC last price: ${last_price}')

For signal-driven bots, pairing Kraken's execution engine with a real-time signal platform like VoiceOfChain gives you the best of both worlds: high-quality entry signals from on-chain and market data, with Kraken handling execution. The key is making sure your signal consumer doesn't fire multiple simultaneous API calls when a cluster of signals arrives at once — queue them and process sequentially with the rate limiter in place.

Kraken Pro API Limits and Upgrading Your Tier

Kraken Pro API limits apply to users who have verified their account and reached the higher trading volume tiers. The main benefit isn't just higher rate limits — it's the faster decay rate that lets you sustain more consistent API traffic without hitting the ceiling. For bots running market-making strategies or scalping algorithms, the difference between 0.33/sec and 1/sec decay is substantial.

To upgrade your Kraken API tier, you need to complete the full KYC verification process and, in some cases, demonstrate trading volume over 30-day periods. Compared to institutional API access at Coinbase Advanced Trade or the VIP tiers at Gate.io and KuCoin, Kraken's tiering system is relatively straightforward — it's tied to account verification level and trading volume rather than requiring separate applications.

Frequently Asked Questions

What is the Kraken API rate limit for free/unverified accounts?
Unverified Kraken accounts have access to public endpoints (ticker, order book, OHLC) without strict rate limits, but private endpoints require at least Starter verification. Starter tier gives you a counter max of 15 with a 0.33/sec decay rate, which supports roughly one sustained request every 3 seconds for private calls.
Does placing a Kraken API limit order count against the rate limit?
Trading endpoints like AddOrder and CancelOrder on Kraken consume 0 rate limit tokens — they're not counted against the standard API counter. However, querying private endpoints like OpenOrders or TradesHistory each cost 1 token, so be careful when polling for order status frequently.
What does EAPI:Rate limit exceeded mean in Kraken's API response?
This error means your API key's rate limit counter has been depleted and requests are being rejected. The fix is to slow down your request rate, implement exponential backoff, and wait for the counter to regenerate. Consider switching to WebSocket subscriptions for data that you're currently polling via REST.
Can I use multiple API keys to get around Kraken rate limits?
Each API key has its own rate limit counter, so technically multiple keys have separate buckets. However, Kraken's terms prohibit using multiple accounts to circumvent limits, and excessive usage patterns can trigger account-level restrictions. The proper solution is to upgrade your account tier and optimize your request patterns.
How do Kraken REST API limits compare to Binance or Bybit?
Binance and Bybit generally offer higher raw throughput — Binance allows 1200 request weight per minute on spot, and Bybit's limits are similarly generous. Kraken's limits are more conservative but designed around their token bucket system rather than rolling windows. For most algo trading use cases, Kraken's limits are sufficient if you use WebSockets for market data.
Is there a Kraken WebSocket API and does it have separate limits?
Yes, Kraken offers both public and private WebSocket APIs. Public WebSocket subscriptions (ticker, book, trade, OHLC) don't count against REST rate limits at all. Private WebSocket channels require a token obtained via the REST GetWebSocketsToken endpoint, but once authenticated, order updates stream without consuming your rate limit counter.

Building a Sustainable Kraken API Strategy

Kraken's rate limiting system rewards traders who build thoughtfully over those who brute-force their way through API calls. The token bucket model is actually more forgiving than rolling-window systems used by some other exchanges — a short burst of requests is fine as long as you give the counter time to regenerate. The traders who hit walls repeatedly are almost always polling REST endpoints for data they could get through WebSockets, or checking order status in tight loops when they could use the private WebSocket feed instead.

The full picture for a production-grade Kraken bot: use REST for order placement and account queries, WebSockets for all market data and order updates, implement a local rate limiter based on the token bucket model, and add exponential backoff on any EAPI error. Layer in a signal source like VoiceOfChain for trade entry logic, and you have a system that can run continuously without manual intervention — which is the actual goal.

Pro tip: log every API error with a timestamp and the full response. Rate limit errors cluster predictably around market open, major news events, and liquidation cascades. Reviewing those logs tells you exactly when your bot is most vulnerable and where to optimize first.
◈   more on this topic
◉ basics Mastering the ccxt library documentation for crypto traders ⌂ exchanges Mastering the Binance CCXT Library for Crypto Traders ⌬ bots Best Crypto Trading Bots 2025: Profitable AI-Powered Strategies