Counter-Strike Boost API
A public, keyless HTTP API for game panels and tools: browse and install CS 1.6 plugins, addon packs, and assemble a complete ready-to-run server.
Introduction #
Everything under /v1 is public and read-only. There is no signup, no OAuth
dance and no key to wait for — a bare curl against any endpoint works right now:
curl "https://api.counter-strike-boost.com/v1/plugins?per_page=20"An API key exists, but it is purely a limits upgrade — see API keys. The three surfaces are:
The three APIs #
Browse the plugin directory and download a plugin. .amxx binaries are compiled on demand — we never store them.
Curated packs that bundle several plugins. Each bundled plugin ships with a ready-to-use install_url.
Assemble ReHLDS, ReGameDLL, Metamod, AMX Mod X, auth, anti-cheat and bots into one archive — validated before you download.
ReferenceBase URL and versioning #
All endpoints live under one host. The main website domain does not serve the API — use
the api. subdomain.
| Base URL | https://api.counter-strike-boost.com |
|---|---|
| Version | v1, carried in the path. A breaking change ships as v2; v1 only ever gains fields. |
| Transport | HTTPS only, HTTP/2. Plain HTTP is redirected. |
| Methods | GET everywhere. There is no write surface on /v1. |
| Content type | application/json; charset=utf-8, except file downloads. |
| CORS | Access-Control-Allow-Origin: * without credentials — call it straight from a browser frontend. |
Add fields defensively: we add response fields without notice, so parse leniently and never assume a fixed key set.
Authentication #
Two tiers. Which one you get is decided by a single thing: whether you sent an
Authorization header at all.
| Tier | Trigger | Identified by | Scopes |
|---|---|---|---|
| Anonymous | no Authorization header |
client IP | plugins:read, addons:read, server:read |
| Key | Authorization: Bearer csbk_… |
the key | whatever the key was issued with |
The anonymous path is taken only when the header is absent. A header that is
present but malformed, unknown, disabled or expired returns 401. Falling back to anonymous
would let a rotting key go unnoticed until it hit the much lower keyless ceiling and produced a
confusing 429 instead of the real problem.
API keys #
Running a panel that installs at scale? Ask for a key and send it as a bearer token. Same endpoints,
much higher limits, and no per-IP compile or build cap. Keys look like csbk_….
curl -H "Authorization: Bearer csbk_your_key_here" \
"https://api.counter-strike-boost.com/v1/plugins"Keys are scoped — plugins:read, addons:read, server:read — and carry
their own per-minute and per-day quota. A request needing a scope the key lacks returns
403 insufficient_scope with the required scopes listed.
Request a key
Rate limits #
Fixed-window counters. Call /v1/meta at any time to read the exact
numbers that apply to you — the defaults below are operator-tunable and the live values always win.
| Bucket | Window | Applies to | Default |
|---|---|---|---|
| Requests | 1 minute | anonymous, per IP | see rate_limits.per_minute |
| Requests | 1 day | anonymous, per IP | see rate_limits.per_day |
| Compiles ( kind=amxx, kind=zip) | 1 hour | anonymous, per IP | 60 |
| Server builds ( server-builder/download) | 1 hour | anonymous, per IP | 10 |
| Compiler flood brake | 1 minute | everyone, site-wide | 40 |
| Key quota | 1 min / 1 day | per key | issued per key |
The compile and build buckets exist because those two calls are the only genuinely expensive ones:
a .amxx download runs a native compiler, and a server build reads hundreds of files. Plain JSON
reads and kind=sma only face the general limits.
Exceeding a bucket returns 429 rate_limited with a Retry-After header.
Back off for that many seconds — retrying immediately just burns the next window.
Errors #
Every error is JSON with the same envelope: status is false and error is a
stable machine-readable code. Branch on error, never on the human wording. Some codes add
context fields — those are listed with the endpoint that raises them.
{
"allowed": ["amxx", "sma", "zip"],
"error": "invalid_kind",
"status": false
}Codes you can hit on any endpoint:
| Status | error | Meaning |
|---|---|---|
| 401 | unauthorized | Bearer token missing the csbk_ prefix, or unknown. Also returned to keyless callers if an operator has switched keyless access off. |
| 401 | key_disabled | The key exists but was disabled. |
| 401 | key_expired | The key is past its expiry date. |
| 403 | insufficient_scope | Key lacks the scope. Body carries required: [...]. |
| 404 | not_found | No such slug/version, or it is not published. |
| 429 | rate_limited | Bucket exhausted. Body carries retry_after (seconds); same value in the Retry-After header. |
| 500 | query_failed | Our database hiccuped. Safe to retry. |
| 503 | api_disabled | The whole API is switched off by an operator. Rare and brief. |
Drafts and unpublished versions are invisible to the API — they return 404 exactly
like a slug that never existed. There is no way to distinguish the two, by design.
Service metadata #
/v1/meta
plugins:read
addons:read
auth optional
Everything a client needs to configure itself at startup: the plugin categories that actually have content, the AMX Mod X toolchains you may pin, the full endpoint map, and — most usefully — the exact rate limits applied to the caller making this request. Call it once on boot rather than hardcoding limits.
Parameters
None. This endpoint takes no parameters.
Response fields
| Field | Type | Notes |
|---|---|---|
auth |
string | "anonymous" or "key" — which tier served this request. |
authenticated |
bool | Handy sanity check: send a key, get true. Still false? Your header never arrived. |
scopes |
string[] | What the caller may do. Anonymous callers get all three read scopes. |
amxx_toolchains |
string[] | Valid values for the amxx query parameter on plugin downloads. |
plugin_categories |
object[] | Categories with at least one published plugin, plus their counts. Empty categories are omitted, so this is safe to render as a filter list. |
rate_limits |
object | The live per-minute and per-day limits for this caller. |
A key that is disabled or expired fails here too, which makes /v1/meta
the cheapest possible health check for an integration.
curl "https://api.counter-strike-boost.com/v1/meta"const res = await fetch(
"https://api.counter-strike-boost.com/v1/meta"
);
const data = await res.json();
if (!data.status) {
throw new Error(data.error); // stable machine-readable code
}<?php
$body = file_get_contents(
"https://api.counter-strike-boost.com/v1/meta"
);
$data = json_decode($body, true);
if (empty($data['status'])) {
throw new RuntimeException($data['error'] ?? 'request_failed');
}import requests
r = requests.get(
"https://api.counter-strike-boost.com/v1/meta",
timeout=30,
)
r.raise_for_status()
data = r.json(){
"amxx_toolchains": ["1.8.2", "1.9", "1.10"],
"api_version": "v1",
"auth": "anonymous",
"authenticated": false,
"docs": "https://counter-strike-boost.com/developers",
"endpoints": {
"addon_detail": "/v1/addons/{slug}",
"addons": "/v1/addons",
"meta": "/v1/meta",
"plugin_detail": "/v1/plugins/{slug}",
"plugin_download": "/v1/plugins/{slug}/download/{version}?kind=amxx|sma|zip",
"plugins": "/v1/plugins",
"server_builder_component": "/v1/server-builder/components/{slug}",
"server_builder_download": "/v1/server-builder/download?components=…&optimized=1",
"server_builder_file": "/v1/server-builder/file?path=…&components=…&optimized=1",
"server_builder_meta": "/v1/server-builder/meta",
"server_builder_resolve": "/v1/server-builder/resolve?components=…&optimized=1"
},
"plugin_categories": [
{ "category": "gameplay", "count": 39 },
{ "category": "admin", "count": 35 },
{ "category": "fun", "count": 30 },
{ "category": "hud-info", "count": 26 }
],
"rate_limits": { "per_day": 1500, "per_minute": 15 },
"scopes": ["plugins:read", "addons:read", "server:read"],
"status": true
}Conventions #
| Envelope | Successful JSON responses always carry "status": true; errors carry "status": false and an error code. |
|---|---|
| Key order | Object keys come back alphabetically sorted. Do not rely on it — parse by name. |
| Timestamps | Strings in YYYY-MM-DD HH:MM:SS, UTC. An unset timestamp is "", not null. |
| Empty vs null | Lists that are empty come back as [] on list endpoints. A few nested fields (e.g. component rules, build notes) are null when empty — handle both. |
| Pagination | page_n (1-based, max 100000) and per_page (1–100, default 24). Out-of-range values are clamped, not rejected. Responses echo page, per_page, total, total_pages. |
| Ordering | List endpoints sort by download count, descending. Not configurable. |
| Slugs | Lowercase, hyphenated, stable. Use them as your foreign key — names and versions change, slugs do not. |
| Ready-made URLs | Responses embed detail_url, page_url, install_url and download_url. Follow them rather than string-building paths yourself. |
| Downloads | Binary responses set Content-Disposition: attachment with the correct filename. With curl, -OJ honours it. |









