EchoScan
UNQ
STB
#···
Cn
En
Jp

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 signal
  • projection.<module>.status: module verdict enum PASS | WARN | FAIL
  • analysis.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_detection and analysis.proxy.status as direct anti-fraud signals
  • Pro exposes richer module observations (speech, screen, webgl) for rule composition and attribution
  • Pro-only history query supports days or from/to and returns summary + 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(())
}
  • days is mutually exclusive with from/to
  • from and to must 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 logic
  • analysis.browser.* and analysis.os.*: environment consistency fields
  • projection.bot_detection and analysis.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 dashboards
  • timeline: time-series access details
  • days and from/to are mutually exclusive; date format is YYYY-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