REST / JSON

API docs

JSON API: prepaid key balance, per-request billing, the same engine as the web UI.

Quick start in three calls

  1. Create a key — you get a csscl_… with a trial balancecurl -X POST https://css-cleaner.ru/api/v1/key -H "Content-Type: application/json" -d '{"name":"my-app"}'
  2. Top up the balance: card, SBP, crypto or the sandboxcurl -X POST https://css-cleaner.ru/api/v1/topup -d 'key=csscl_XXXX&amount=500&provider=yookassa'
  3. Send CSS — get clean CSS back plus a reportcurl -X POST https://css-cleaner.ru/api/v1/dedup -H "X-API-Key: csscl_XXXX" -d '{"css":".a{color:red}.a{color:red}"}'

There is no account: the key is the wallet. Lose the key, lose the balance.

Authentication

Pass the key in any of these three ways.

X-API-Key: csscl_XXXXXXXXXXXXXXXX
Authorization: Bearer csscl_XXXXXXXXXXXXXXXX
POST /api/v1/dedup?key=csscl_XXXXXXXXXXXXXXXX

Without a key you get 20 free requests per day per IP — fine for tests, get a key for production.

Endpoints

Method and pathWhat it doesPrice
POST /api/v1/dedupRemoves duplicates and empty rules, safely merges repeated selectors.$0.0011
POST /api/v1/filterKeeps only the rules that actually match the HTML you send.$0.0022
POST /api/v1/blockExtracts one block's styles, including inherited html/body rules and every var() it needs.$0.0033
POST /api/v1/keyCreate a key with a trial balancefree
GET /api/v1/keyBalance, spend, request count, current pricesfree
POST /api/v1/topupTop-up invoice — returns the checkout URLfree
POST /api/dedup · /api/filter · /api/blockThe same three jobs, key-less and unbilledfree

Request parameters

POST /api/v1/dedup

FieldTypeRequiredMeaning
cssstringyesthe whole stylesheet, exactly as in the file
strip_commentsboolnostrip comments (off by default)
merge_overridesboolnomerge identical selectors into one rule — only when properties do not conflict

POST /api/v1/filter

FieldTypeRequiredMeaning
cssstringyesthe whole stylesheet, exactly as in the file
htmlstringyesthe page HTML the CSS is cleaned against
drop_keyframesboolnodrop @keyframes nothing animates
drop_fontsboolnodrop unused @font-face

POST /api/v1/block

FieldTypeRequiredMeaning
cssstringyesthe whole stylesheet, exactly as in the file
htmlstringyesthe page HTML the CSS is cleaned against
targetstringyesblock selector: .card, #hero, main .btn
pruneboolnodrop declarations the cascade overrides later anyway
drop_keyframesboolnodrop @keyframes nothing animates
drop_fontsboolnodrop unused @font-face

POST /api/v1/topup

FieldTypeRequiredMeaning
keystringyesthe API key to top up
amountnumberyesamount in rubles: 100 to 100000
providerstringnoyookassa · robokassa · cryptocloud · demo (empty = first available)

Response

A successful call returns JSON with the result and a report. Money is in kopecks.

{
  "ok": true,
  "endpoint": "block",
  "charged": 30,
  "price": 30,
  "balance": 970,
  "output": ":root { --brand: #3b82f6; } body { color: #222; } .card { padding: 24px; }",
  "report": {
    "rules_total": 14, "rules_kept": 9, "rules_dropped": 5,
    "elements_matched": 1, "inherited_kept": ["html", "body", ".content"],
    "var_names": ["--brand", "--gap", "--text"],
    "saved_bytes": 412, "reduction": 38.4
  }
}
FieldMeaning
outputthe cleaned CSS as a single string
charged · price · balancewhat was charged, the price, the remaining balance
report.saved_bytes · report.reductionbytes saved and the percentage
report.rules_before · rules_after · duplicates · empty · merged_groupsdedup stats: rules before/after, duplicates, empty rules, merges
report.rules_kept · rules_dropped · elements_matched · keyframes_dropped · fonts_droppedfilter stats: kept, dropped, how many elements matched
report.inherited_kept · var_names · decls_pruned · targetfor a block: inherited selectors, variable names, pruned declarations

Errors

Every error is JSON of the shape {"error": "…"}.

HTTPMeaning
400missing css/html or malformed JSON
401key unknown or not supplied
402insufficient balance
403key disabled
404unknown endpoint, e.g. /api/v1/pretty
413input larger than 2 MB
429daily free limit reached

Limits

Code samples

JavaScript (fetch)

const r = await fetch("https://css-cleaner.ru/api/v1/filter", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": "csscl_XXXX" },
  body: JSON.stringify({ html: document.documentElement.outerHTML, css, drop_keyframes: true }),
});
const { output, report } = await r.json();
console.log(`−${report.saved_bytes} б, −${report.rules_dropped} правил`);

Python (requests)

import requests

r = requests.post("https://css-cleaner.ru/api/v1/block",
                  headers={"X-API-Key": "csscl_XXXX"},
                  json={"html": html, "css": css, "target": ".card", "prune": True},
                  timeout=60)
r.raise_for_status()
print(r.json()["output"], r.json()["balance"])