EchoScan SDK Integration Guide
Integration Overview
Recommended flow: run Browser Verifier in the browser to get imprint, then query Lite / Pro reports from your server.
Browser side is collection + submit only; report queries and risk decisions should stay on the server.
Browser Verifier Frontend
NPM ESM
npm install @echoscan/browser-verifier
import { createEchoScan } from '@echoscan/browser-verifier'
const { imprint } = await createEchoScan().run()
await fetch('/your-server/imprint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ imprint })
})
CDN ESM / UMD
<script type="module">
import { createEchoScan } from 'https://cdn.echoscan.org/v1/echoscan.esm.js'
const { imprint } = await createEchoScan().run()
console.log(imprint)
</script>
<script src="https://cdn.echoscan.org/v1/echoscan.umd.js"></script>
<script>
window.EchoScan.createEchoScan().run().then(({ imprint }) => console.log(imprint))
</script>
Lite Integration
Lite requires no API key and is designed for public, lightweight risk checks.
Node
npm install @echoscan/echoscan
import { createLiteClient } from '@echoscan/echoscan'
const lite = createLiteClient()
const report = await lite.getReport(imprint)
Go
go get github.com/ozzxzzo/fingerprint-system/echoscan/packages/go@latest
package main
import (
"context"
"log"
echoscan "github.com/ozzxzzo/fingerprint-system/echoscan/packages/go"
)
func main() {
imprint := "fp_session_xxx"
lite, err := echoscan.NewLiteClient()
if err != nil {
log.Fatal(err)
}
report, err := lite.GetReport(context.Background(), imprint)
if err != nil {
log.Fatal(err)
}
log.Printf("lyingCount=%v", report["lyingCount"])
}
Python
pip install echoscan
from echoscan import EchoScanLiteClient
imprint = "fp_session_xxx"
lite = EchoScanLiteClient()
report = lite.get_report(imprint)
print(report.get("lyingCount"))
Rust
[dependencies]
echoscan = "0.1.1"
use echoscan::LiteClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let imprint = "fp_session_xxx";
let lite = LiteClient::new()?;
let report = lite.get_report(imprint).await?;
println!("{}", report["lyingCount"]);
Ok(())
}
Lite Response Mapping
{
"analysis": {
"browser": {},
"os": {},
"hash": {},
"proxy": {}
},
"lyingCount": 0,
"projection": {
"audio": { "status": "PASS" },
"canvas": { "status": "PASS" },
"font": { "status": "PASS" },
"ip-geo-timezone": { "status": "PASS" },
"navigator": { "status": "PASS" },
"screen": { "status": "PASS" },
"speech": { "status": "PASS" },
"webgl": { "status": "PASS" },
"webrtc": { "status": "PASS" }
}
}
lyingCount: direct risk segmentation signalprojection.<module>.status: module verdict enumPASS | WARN | FAILanalysis.proxy.status: proxy risk state (PASS/WARN/FAIL)
Pro Integration
Pro requires a server-side API key and is built for server risk policy and operations analytics.
- Compared with Lite, Pro adds
projection.bot_detectionandanalysis.proxy.statusas direct anti-fraud signals - Pro exposes richer module observations (
speech,screen,webgl) for rule composition and attribution - Pro-only history query supports
daysorfrom/toand returnssummary+timeline
Node
npm install @echoscan/echoscan
import { createProClient } from '@echoscan/echoscan'
const pro = createProClient({ apiKey: process.env.ECHOSCAN_PRO_KEY })
const report = await pro.getReport(imprint)
const historyByDays = await pro.getHistory(imprint, { days: 7 })
const historyByRange = await pro.getHistory(imprint, {
from: '2026-03-01',
to: '2026-03-18'
})
Go
go get github.com/ozzxzzo/fingerprint-system/echoscan/packages/go@latest
package main
import (
"context"
"log"
echoscan "github.com/ozzxzzo/fingerprint-system/echoscan/packages/go"
)
func main() {
imprint := "fp_session_xxx"
days := 7
pro, err := echoscan.NewProClient("es_xxx_yyy")
if err != nil {
log.Fatal(err)
}
report, err := pro.GetReport(context.Background(), imprint)
if err != nil {
log.Fatal(err)
}
history, err := pro.GetHistory(context.Background(), imprint, echoscan.HistoryQuery{
Days: &days,
})
if err != nil {
log.Fatal(err)
}
_, _ = report, history
}
Python
pip install echoscan
from echoscan import EchoScanProClient
imprint = "fp_session_xxx"
pro = EchoScanProClient("es_xxx_yyy")
report = pro.get_report(imprint)
history = pro.get_history(imprint, days=7)
print(report.get("lyingCount"), history.get("summary"))
Rust
[dependencies]
echoscan = "0.1.1"
use echoscan::{HistoryQuery, ProClient};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let imprint = "fp_session_xxx";
let pro = ProClient::new("es_xxx_yyy")?;
let report = pro.get_report(imprint).await?;
let history = pro
.get_history(imprint, HistoryQuery::Days { days: 7, recent: None })
.await?;
println!("{} {}", report["lyingCount"], history["summary"]);
Ok(())
}
daysis mutually exclusive withfrom/tofromandtomust be provided together- Date format is fixed to
YYYY-MM-DD
Pro Response Mapping
{
"analysis": {
"browser": {
"brand": "Google Chrome",
"browser_version": "146.0.x",
"browser_version_consistency_status": "PASS",
"rendering_engine": "Blink"
},
"os": {
"os": "Windows",
"os_consistency_status": "PASS",
"version": "11"
},
"hash": {
"accessCount": 31,
"calculatedAt": "2026-03-19T10:27:25+09:00",
"stableHash": "....",
"uniqueHash": "...."
},
"proxy": { "status": "PASS" }
},
"lyingCount": 0,
"projection": {
"bot_detection": {
"status": "PASS",
"data": { "is_bot": "No" }
},
"screen": {
"status": "PASS",
"data": { "resolution": "1920 x 1080" }
},
"speech": {
"status": "PASS",
"data": {
"default_voice_lang": "en-US",
"default_voice_name": "Microsoft David - English (United States)"
}
},
"webgl": {
"status": "PASS",
"data": {
"unmasked_vendor": "Google Inc. (NVIDIA)",
"unmasked_renderer": "NVIDIA GeForce RTX 3060"
}
}
}
}
analysis.hash.accessCount: historical access count for returning-user logicanalysis.browser.*andanalysis.os.*: environment consistency fieldsprojection.bot_detectionandanalysis.proxy.status: direct anti-bot and proxy policy inputs
Pro History Mapping
{
"imprint": "fp_session_...",
"range": {
"from": "2026-03-01",
"to": "2026-03-18"
},
"recent": 20,
"summary": {},
"timeline": []
}
summary: aggregated metrics for operations dashboardstimeline: time-series access detailsdaysandfrom/toare mutually exclusive; date format isYYYY-MM-DD
Error Shape
{
"code": "auth_failed",
"httpStatus": 401,
"message": "Authentication failed",
"requestId": "req_...",
"retryable": false
}
Use code as your primary branch key; treat message as display-only.
API Key Application
- Send app information to
contact@echoscan.org - Integration and technical support:
support@echoscan.org - Privacy and security issues:
security@echoscan.org - Pro key is issued after review
- Keep keys in server environment variables only, never in frontend code