BelgelerOtomasyon
Betiklerle otomasyon
Aynı bilgisayardaki bir betik bir profili açıp tarayıcısını devralabilir. Aldığı profil, elle açtığınız profilin aynısıdır — aynı parmak izi, aynı bağlantı, aynı çerezler.
Uygulamanın arayüzü yalnızca İngilizce ve Rusçadır. Düğme ve ayar adları bu sayfada İngilizce arayüzde göründüğü gibi yazılmıştır.
Yerel API nedir
Yerel API, uygulamanın içindeki küçük bir hizmettir. Yalnızca bu bilgisayarda ve yalnızca anahtarınızı taşıyan isteklere yanıt verir. Onunla bir betik profilleri listeleyebilir, başlatıp durdurabilir ve bir otomasyon kitaplığının başlatılan tarayıcıya bağlandığı adresi alabilir.
- Her plan, ücretsiz olan da dahil.
- Yalnızca bu bilgisayar:
127.0.0.1üzerinde dinler ve ağa açılamaz. - Siz açana kadar kapalıdır.
- Profiller uygulamada oluşturulur. API, sahip olduğunuz profilleri çalıştırır; profil oluşturmaz ve düzenlemez.
Açın
- Settings › API & Automation bölümünü açın ve Local API seçeneğini etkinleştirin. Yanındaki satır Running on this computer only. olarak değişir.
- Port değerini olduğu gibi bırakın — değiştirmediyseniz
48361— ya da Random free port düğmesine basın. - API key değerini hemen Copy ile kopyalayın: anahtarın kendisi hiçbir zaman gösterilmez ve sayfadan ayrıldıktan sonra yeniden kopyalanamaz — yalnızca değiştirilebilir. Uzunluğu 64 karakterdir.

- Address
- Hizmetin yanıt verdiği yer; yanında Copy düğmesi bulunur — varsayılan olarak
http://127.0.0.1:48361. - Regenerate…
- Yeni bir anahtar oluşturur. Eskisi anında çalışmayı bırakır; onunla verilmiş tarayıcı adresleri de öyle.
- API documentation
- Başvuruyu açar.
Not. Anahtar bir dosyada değil, sistemin kimlik bilgisi deposunda tutulur. Bir betik, portu koda gömmek yerine adresi uygulamanın yazdığı dosyadan — Liminal’ın veri klasöründeki Local API/status.json — okumalıdır; başvuru dosyanın nerede olduğunu açıklar.
İlk istek
Her istek anahtarı bir başlıkta taşır. Hizmete çalışıp çalışmadığını sorun:
curl -H 'Authorization: Bearer <key>' http://127.0.0.1:48361/v1/status{"status":"running","version":"<version>","signedIn":true}signedIn, uygulamaya giriş yapmış biri olup olmadığını söyler. Profillere dokunan işlemler bunu gerektirir: yoksa not_signed_in yanıtını verirler.
Bir profil bulun ve başlatın
Profilleri listeleyin — yanıt sayfalar hâlinde gelir ve ada, çalışma alanına, klasöre ve duruma göre süzülebilir:
curl -H 'Authorization: Bearer <key>' http://127.0.0.1:48361/v1/profilesİstediğiniz profilin id değerini alın ve profili başlatın:
curl -X POST -H 'Authorization: Bearer <key>' http://127.0.0.1:48361/v1/profiles/<profile-id>/start{
"id": "<profile-id>",
"status": "running",
"cdpDiscoveryUrl": "http://127.0.0.1:48361/devtools/<token>/json/version",
"cdpBrowserUrl": "ws://127.0.0.1:9222/devtools/browser/<token>",
"seleniumDebuggerUrl": "127.0.0.1:9222",
"chromedriverPath": "/Applications/Liminal.app/.../chromedriver",
"debugPort": 9222,
"debugAddress": "127.0.0.1:9222",
"externalIp": "203.0.113.10",
"countryCode": "DE"
}cdpBrowserUrl- Puppeteer ve Playwright’ın bağlandığı adres.
seleniumDebuggerUrl,chromedriverPath- Selenium’un ihtiyaç duyduğu şeyler: hata ayıklayıcı adresi ve tarayıcıyla eşleşen, uygulamayla birlikte gelen sürücü.
externalIp,countryCode- Profil başladığında bağlantısının nasıl göründüğü.
Uygulama profili, Open düğmesine basmışsınız gibi başlatır. Zaten açık olan bir profil yeniden başlatılmaz — başvuru, çalışan bir profile nasıl bağlanılacağını anlatır.
Kitaplığınızı bağlayın
Her örnek eksiksizdir: adres dosyasını okur, bir profili adına göre bulur, başlatır ve bir sayfa açar.
import { readFileSync } from 'node:fs'
import puppeteer from 'puppeteer-core'
// Local API/status.json, inside Liminal's user-data directory. The settings
// screen shows the absolute path; that path and the key are your script’s to
// keep — the app puts neither into the environment for you.
const { address } = JSON.parse(readFileSync(process.env.LIMINAL_ADDRESS_FILE, 'utf8'))
async function call(path, init) {
const response = await fetch(address + path, {
...init,
headers: { Authorization: `Bearer ${process.env.LIMINAL_API_KEY}` },
})
const body = await response.json()
if (!response.ok) throw new Error(body.error.code)
return body
}
const { items } = await call('/v1/profiles?name=' + encodeURIComponent('Shop EU'))
const started = await call(`/v1/profiles/${items[0].id}/start`, { method: 'POST' })
const browser = await puppeteer.connect({ browserWSEndpoint: started.cdpBrowserUrl })
const page = await browser.newPage()
await page.goto('https://example.com')
console.log(await page.title())
await browser.disconnect()import { readFileSync } from 'node:fs'
import { chromium } from 'playwright'
// Local API/status.json, inside Liminal's user-data directory. The settings
// screen shows the absolute path; that path and the key are your script’s to
// keep — the app puts neither into the environment for you.
const { address } = JSON.parse(readFileSync(process.env.LIMINAL_ADDRESS_FILE, 'utf8'))
async function call(path, init) {
const response = await fetch(address + path, {
...init,
headers: { Authorization: `Bearer ${process.env.LIMINAL_API_KEY}` },
})
const body = await response.json()
if (!response.ok) throw new Error(body.error.code)
return body
}
const { items } = await call('/v1/profiles?name=' + encodeURIComponent('Shop EU'))
const started = await call(`/v1/profiles/${items[0].id}/start`, { method: 'POST' })
const browser = await chromium.connectOverCDP(started.cdpBrowserUrl)
const page = await browser.contexts()[0].newPage()
await page.goto('https://example.com')
console.log(await page.title())
await browser.close()import json
import os
import urllib.parse
import urllib.request
from playwright.sync_api import sync_playwright
# Local API/status.json, inside Liminal's user-data directory. The settings
# screen shows the absolute path; that path and the key are your script’s to
# keep — the app puts neither into the environment for you.
with open(os.environ["LIMINAL_ADDRESS_FILE"], encoding="utf-8") as handle:
address = json.load(handle)["address"]
def call(path, method="GET"):
request = urllib.request.Request(address + path, method=method)
request.add_header("Authorization", "Bearer " + os.environ["LIMINAL_API_KEY"])
with urllib.request.urlopen(request) as response:
return json.load(response)
profile = call("/v1/profiles?name=" + urllib.parse.quote("Shop EU"))["items"][0]
started = call(f"/v1/profiles/{profile['id']}/start", method="POST")
with sync_playwright() as playwright:
browser = playwright.chromium.connect_over_cdp(started["cdpBrowserUrl"])
page = browser.contexts[0].new_page()
page.goto("https://example.com")
print(page.title())import json
import os
import urllib.parse
import urllib.request
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# Local API/status.json, inside Liminal's user-data directory. The settings
# screen shows the absolute path; that path and the key are your script’s to
# keep — the app puts neither into the environment for you.
with open(os.environ["LIMINAL_ADDRESS_FILE"], encoding="utf-8") as handle:
address = json.load(handle)["address"]
def call(path, method="GET"):
request = urllib.request.Request(address + path, method=method)
request.add_header("Authorization", "Bearer " + os.environ["LIMINAL_API_KEY"])
with urllib.request.urlopen(request) as response:
return json.load(response)
profile = call("/v1/profiles?name=" + urllib.parse.quote("Shop EU"))["items"][0]
started = call(f"/v1/profiles/{profile['id']}/start", method="POST")
options = webdriver.ChromeOptions()
options.debugger_address = started["seleniumDebuggerUrl"]
driver = webdriver.Chrome(service=Service(started["chromedriverPath"]), options=options)
driver.get("https://example.com")
print(driver.title)
driver.quit()import { readFileSync } from 'node:fs'
import { Builder } from 'selenium-webdriver'
import chrome from 'selenium-webdriver/chrome.js'
// Local API/status.json, inside Liminal's user-data directory. The settings
// screen shows the absolute path; that path and the key are your script’s to
// keep — the app puts neither into the environment for you.
const { address } = JSON.parse(readFileSync(process.env.LIMINAL_ADDRESS_FILE, 'utf8'))
async function call(path, init) {
const response = await fetch(address + path, {
...init,
headers: { Authorization: `Bearer ${process.env.LIMINAL_API_KEY}` },
})
const body = await response.json()
if (!response.ok) throw new Error(body.error.code)
return body
}
const { items } = await call('/v1/profiles?name=' + encodeURIComponent('Shop EU'))
const started = await call(`/v1/profiles/${items[0].id}/start`, { method: 'POST' })
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options().debuggerAddress(started.seleniumDebuggerUrl))
.setChromeService(new chrome.ServiceBuilder(started.chromedriverPath))
.build()
await driver.get('https://example.com')
console.log(await driver.getTitle())
await driver.quit()İpucu. Profilin zaten sahip olduğu tarayıcıya bağlanın. Kitaplığın kendi tarayıcısını başlatmasına izin vermeyin — o tarayıcıda profilin ne parmak izi ne de çerezleri olur.
Profili durdurun
curl -X POST -H 'Authorization: Bearer <key>' http://127.0.0.1:48361/v1/profiles/<profile-id>/stopDurdurmak, profili Close düğmesinin yaptığı gibi kapatır. Kapanmayan bir profil için zorla durdurma da vardır.
Bilmekte fayda var
| Soru | Yanıt |
|---|---|
| Bir betik benim gördüğümden farklı bir tarayıcı mı görür? | Hayır. Parmak izi ve bağlantı, profili elle açtığınızdaki gibi uygulanır ve aynı korumalar geçerlidir. |
| Siteler tarayıcının otomatikleştirildiğini görür mü? | API üzerinden başlatılan bir profilde otomasyonun alışılmış izleri gizlenir. Bu kapatılamaz. |
| Başsız (headless) mod var mı? | Hayır. API bir profili uygulamanın yaptığı gibi başlatır. |
| İsteklerde bir sınır var mı? | Plana bağlı bir kota yoktur. |
| Komut satırı aracı ya da kaydedilmiş senaryolar var mı? | Hayır. Otomasyonun yolu Yerel API’dir. |
| Bir şey ters gittiğinde ne alırım? | Bir durum kodu ve dallanmak için kısa bir code — invalid_key, not_signed_in, profile_already_running ve diğerleri. Başvuruda işlem bazında listelenirler. |
Yayımlanan uygulamayla karşılaştırıldı: Ekim 2026. Uygulama bu sayfada yazandan farklı davranıyorsa sayfa yanlıştır — [email protected] adresine yazın. Her sürümde nelerin değiştiği Yenilikler bölümündedir.