Kalkan Local API, kendi betiklerinizle profilleri, proxy'leri ve klasörleri yönetmenizi, tarayıcıları açıp kapatmanızı ve onları Playwright, Puppeteer ya da Selenium ile kullanmanızı sağlar. Kendi bilgisayarınızda çalışan Kalkan masaüstü uygulamasının sunduğu bir REST API'dir:
http://127.0.0.1:50360/api/v1
Tüm istekler ve yanıtlar JSON'dur. API; Starter, Pro ve Unlimited planlarında vardır (denemede yoktur).
Açma ve anahtarı alma
- Kalkan → Ayarlar → API bölümünü açın ve API'yi etkinleştirin.
- 50360 numaralı port bilgisayarınızda doluysa portu değiştirin.
- API anahtarını kopyalayın (
kk_ile başlar). Yeni anahtar üret yeni bir anahtar oluşturur; eskisi o anda geçersiz olur.
API, Kalkan uygulaması açık olduğu sürece çalışır. Pencere olmadan çalışması gereken sunucu ve betikler için aynı API'yi sunan geliştirici komutu adb api de vardır.
Kimlik doğrulama ve güvenlik
- Anahtarı her istekte
X-Token: <anahtar>başlığıyla gönderin.Authorization: Bearer <anahtar>da kabul edilir. - Anahtar yoksa ya da yanlışsa
401 unauthorizeddöner. Bir dakika içinde 10 yanlış anahtardan sonra API 60 saniye boyunca429 lockedyanıtı verir. - API yalnızca
127.0.0.1üzerinde dinler ve yalnızca127.0.0.1ya dalocalhostadresine gelen isteklere yanıt verir (aksi halde403 forbidden_host). Başka bilgisayarlardan erişilemez. - Web sayfaları için değil, betikler içindir:
Originbaşlığı taşıyan istekler (tarayıcıların gönderdiği)403 forbidden_originile reddedilir; CORS yoktur. - Tek gizli bilgi anahtardır. Kod depolarına koymayın; sızarsa yenisini üretin.
- Planınızda API yoksa her çağrı
403 plandöner.GET /statusher zaman çalışır ve planınızın API'yi içerip içermediğiniapi_allowedalanında bildirir.
Yanıtlar ve hatalar
Başarılı bir çağrı {"ok": true, "data": …}, başarısız bir çağrı {"ok": false, "error": {"code": "…", "message": "…"}} döner.
{"ok": true, "data": {"id": "…", "running": true, "ws": "ws://127.0.0.1:49731/devtools/browser/…", "debug_port": 49731, "pid": 12345}}
{"ok": false, "error": {"code": "unauthorized", "message": "missing or wrong API key (send it as the X-Token header)"}}
| Durum | Kodlar | Anlamı |
|---|---|---|
| 200 / 201 / 202 | Tamam / oluşturuldu / arka planda başlatıldı (wait: false) | |
| 400 | bad_request | Eksik ya da geçersiz alan |
| 401 | unauthorized | API anahtarı yok ya da yanlış |
| 403 | plan, forbidden_host, forbidden_origin | Planda API yok, Host yanlış ya da istek bir web sayfasından geliyor |
| 404 / 405 | not_found, method_not_allowed | Böyle bir profil / proxy / uç nokta yok ya da HTTP yöntemi yanlış |
| 409 | running, direct, ledger, cross_os | Profil açık ya da açılış bir karar gerektiriyor. direct: profilin proxy'si yok (allow_direct: true ile tekrarlayın). ledger: proxy'nin çıkış IP'si yakın zamanda başka profillerce kullanılmış; cross_os: profilin işletim sistemi bu bilgisayarda bu motora uymuyor (force: true ile tekrarlayın). Mesaj durumu açıklar. |
| 429 | locked | Çok fazla yanlış anahtar, 60 saniye bekleyin |
| 500 | internal, launch_failed | Beklenmeyen hata ya da tarayıcı başlatılamadı |
| 504 | timeout | Tarayıcı timeout süresi içinde açılmadı |
Motorlar
Kalkan'da dört motor vardır: Kalkan Native (önerilen; parmak izini C++ kodunda üreten, 150+ yamalı özel Chromium; uygulama arka planda kurar ve günceller), Kalkan (Chrome patch: gerçek Google Chrome'unuz, yamalı sürücüyle), Kalkan Edge (aynı katman kurulu Microsoft Edge'inizde; oluştururken "engine": "edge") ve Firefox (Windows, macOS ve Linux profilleri). Kalkan, Kalkan Edge ve Kalkan Native profilleri otomasyon için bir DevTools (CDP) uç noktasıyla açılır; Firefox profilleri bu uç nokta olmadan açılır (ws değeri null).
Uç noktalar
Tüm yollar http://127.0.0.1:50360/api/v1 adresine göredir.
| İstek | Ne yapar |
|---|---|
GET /status | Uygulama ve API durumu: app, version, api, api_allowed, plan, running (açık profil sayısı). |
GET /profiles | Profilleri listeler. Filtreler: folder, q (arama), tag, engine (profilin bu listede döndürdüğü engine değeri), proxy (yes | no), status (running | used | new | frozen). Sıralama: sort (name | created | last_used | folder | engine | proxy), desc=1. Sayfalama: page, page_size (varsayılan 100, en fazla 500). {total, page, page_size, items} döner. |
POST /profiles | Profil oluşturur (201). Alanlar: name (zorunlu), engine, os (windows | macos | linux), mode (native | balanced | maximum | gmail | custom; önerilen balanced), folder, tags, notes, start_url, color. Proxy: {type, host, port, username, password} nesnesi (type: http | https | socks5), proxy_user / proxy_pass ile birlikte "socks5://host:port" gibi bir adres ya da pool_id (kayıtlı bir proxy kimliği veya "auto"). |
GET /profiles/{id} | Tek bir profilin tüm ayrıntıları. Proxy şifreleri asla döndürülmez. |
PATCH /profiles/{id} | name, notes, tags, color, start_url, folder, allow_direct, frozen, extensions, bookmarks, proxy (+ proxy_user, proxy_pass) alanlarını düzenler. Parmak izi ve cihaz alanları değiştirilemez (400). |
DELETE /profiles/{id} | Profili siler (profil açıkken 409). |
POST /profiles/{id}/clone | Profili kopyalar; isteğe bağlı yeni bir name verilebilir (201). |
POST /profiles/{id}/start | Profili açar. İsteğe bağlı: url, allow_direct, force, cdp (varsayılan true), wait (varsayılan true), saniye cinsinden timeout (5–180, varsayılan 60). id, name, engine, running, already_running, ws, cdp, debug_port, http, pid döner. wait: false ile hemen 202 {starting: true} yanıtı verir. |
POST /profiles/{id}/stop | Profili kapatır: {stopped}. |
GET /profiles/{id}/status | running, ws, cdp, debug_port, warnings, errors. |
GET /profiles/{id}/cookies | Çerezleri dışa aktarır: ?format=json (varsayılan) ya da netscape. Profil kapalı olmalıdır (aksi halde 409). |
POST /profiles/{id}/cookies | {cookies: …} alanını JSON listesi ya da Netscape metni olarak içe aktarır ve aktarılan sayıyı döner. Profil kapalı olmalıdır. |
PUT /profiles/{id}/proxy | Proxy'yi ayarlar: kayıtlı proxy için {proxy_id}, yeni proxy için {proxy: {…}}, kaldırmak için {proxy: null}. |
GET /running | Açık profiller: [{id, engine, cdp, debug_port, pid}]. |
POST /stop-all | Açık profillerin hepsini kapatır: {stopped: [kimlikler]}. |
GET /foldersPOST /folders | Klasörleri listeler / {name, color?} ile yeni klasör oluşturur (201). |
GET /proxies | Kayıtlı proxy'ler (şifreler asla döndürülmez). |
POST /proxies | Proxy ekler (201): her satırda bir proxy olacak şekilde {text: "…"} ya da {proxies: [...], scheme?, label?}. |
DELETE /proxies/{id} | Kayıtlı bir proxy'yi siler. Profillere bağlı bir proxy yalnız ?force=true ile silinir (o profiller proxy'siz kalır). |
POST /proxies/{id}/check | Proxy'yi test eder: çıkış IP'si, ülke, tür, gecikme, tespit sitelerinin neleri görebildiği ve itibar. |
Örnekler: curl
PowerShell'de curl.exe yazın; orada curl, Invoke-WebRequest komutunun takma adıdır. JSON gövdeleri Git Bash, cmd ya da bir betikten göndermek en kolayıdır.
curl -H "X-Token: kk_..." http://127.0.0.1:50360/api/v1/status
curl -H "X-Token: kk_..." "http://127.0.0.1:50360/api/v1/profiles?status=running&sort=last_used&desc=1"
curl -X POST -H "X-Token: kk_..." -H "Content-Type: application/json" \
-d '{"name": "shop-01", "os": "windows", "mode": "balanced", "proxy": "socks5://1.2.3.4:1080", "proxy_user": "user", "proxy_pass": "pass"}' \
http://127.0.0.1:50360/api/v1/profiles
curl -X POST -H "X-Token: kk_..." -H "Content-Type: application/json" \
-d '{"url": "https://example.com"}' \
http://127.0.0.1:50360/api/v1/profiles/PROFILE_ID/start
Örnekler: Python + Playwright
Proxy'li bir profil oluşturur, açar ve connect_over_cdp ile bağlanır (pip install requests playwright).
import requests
from playwright.sync_api import sync_playwright
API = "http://127.0.0.1:50360/api/v1"
H = {"X-Token": "kk_..."}
def call(method, path, **kw):
r = requests.request(method, API + path, headers=H, timeout=200, **kw).json()
if not r["ok"]:
raise RuntimeError(r["error"]["code"] + ": " + r["error"]["message"])
return r["data"]
prof = call("POST", "/profiles", json={
"name": "shop-01", "os": "windows", "mode": "balanced",
"proxy": {"type": "socks5", "host": "1.2.3.4", "port": 1080,
"username": "user", "password": "pass"},
})
run = call("POST", f"/profiles/{prof['id']}/start")
with sync_playwright() as pw:
browser = pw.chromium.connect_over_cdp(run["ws"])
ctx = browser.contexts[0] # the profile's own context
page = ctx.pages[0] if ctx.pages else ctx.new_page()
page.goto("https://example.com")
print(page.title())
call("POST", f"/profiles/{prof['id']}/stop")
Örnekler: Node.js + Puppeteer
puppeteer-core kullanın: tarayıcıyı Kalkan başlatır, Puppeteer yalnızca ona bağlanır.
const puppeteer = require("puppeteer-core");
const API = "http://127.0.0.1:50360/api/v1";
const H = { "X-Token": "kk_...", "Content-Type": "application/json" };
(async () => {
const res = await fetch(`${API}/profiles/PROFILE_ID/start`, { method: "POST", headers: H, body: "{}" });
const { ok, data, error } = await res.json();
if (!ok) throw new Error(`${error.code}: ${error.message}`);
const browser = await puppeteer.connect({ browserWSEndpoint: data.ws, defaultViewport: null });
const [page] = await browser.pages();
await page.goto("https://example.com");
console.log(await page.title());
await browser.disconnect();
})();
Örnekler: Selenium
Selenium debug_port üzerinden bağlanır. chromedriver'ın ana sürümü tarayıcınınkiyle aynı olmalıdır (Kalkan, bilgisayarınızda kurulu Chrome'u kullanır).
import requests
from selenium import webdriver
API = "http://127.0.0.1:50360/api/v1"
H = {"X-Token": "kk_..."}
run = requests.post(f"{API}/profiles/PROFILE_ID/start", headers=H, json={}).json()["data"]
opts = webdriver.ChromeOptions()
opts.debugger_address = f"127.0.0.1:{run['debug_port']}"
driver = webdriver.Chrome(options=opts)
driver.get("https://example.com")
print(driver.title)
İpuçları
- Betikten viewport ayarlamayın. Profilin ekran boyutu parmak izinin bir parçasıdır. Puppeteer'da
defaultViewport: nullkullanın, Playwright'taviewportvermeyin. - Profilin mevcut bağlamını kullanın. Playwright'ta
new_context()yerinebrowser.contexts[0]alın: yeni bir bağlamda profilin çerezleri ve ayarları yoktur. - Betiğiniz bitince tarayıcıyı kapatmak yerine bağlantıyı kesin ve profili
POST /profiles/{id}/stopile durdurun; böylece Kalkan oturumu düzgünce kaydeder. - Zaten açık bir profili başlatmak aynı uç noktayı
already_running: trueile döner; betiklerstartçağrısını güvenle tekrarlayabilir. - 409 yanıtlarını bilinçli ele alın:
allow_directveforce, bir betiğin profili yanlışlıkla proxy'siz ya da yeniden kullanılan bir IP ile açmaması için vardır.