EchoScan API・導入ガイド
EchoScan は、登録、ログイン、注文、決済、出金、クーポン取得、投票、フォーム送信、パスワードリセットなど、リスク判断が必要なアクセスや業務アクションでブラウザ環境の偽装、自動化アクセス、ネットワーク ID の異常を評価します。
基本フローはシンプルです。ブラウザで実行されるコードが imprint を生成し、保護対象のリクエストと一緒にサーバーへ送ります。サーバー側コードは EchoScan secret key で report を照会し、最終的なリスク判断を行います。
推奨フロー
- 保護したいアクセスまたは業務アクションを選びます。
- ブラウザで実行されるコードで Browser Verifier を呼び出し、
imprintを生成します。 imprintを現在の業務リクエストと一緒にサーバーへ送ります。body、リクエストヘッダー、または自分で実装する独立したリスク判定エンドポイントを利用できます。- サーバーで実行されるコードだけが EchoScan secret key を読み取り、Lite または Pro report を照会します。
- サーバーは
allow、challenge、review、denyなどの最小限の判断結果を返します。
Next.js、Nuxt、Remix、SvelteKit、Laravel、Rails、Django、Vercel Functions、Cloudflare Workers などでは、ブラウザコードとサーバー route が同じリポジトリにある場合があります。重要なのはディレクトリ構成ではなく実行場所です。secret key はサーバー実行環境だけに置いてください。
ブラウザで imprint を生成
Browser Verifier はブラウザ環境のシグナルを収集し、imprint を返します。最終 report は返さず、EchoScan secret key も保持しません。
npm install @echoscan/browser-verifier
import { createEchoScan } from '@echoscan/browser-verifier'
const { imprint } = await createEchoScan().run()
CDN 方式はビルドなしのページや短いデモに適しています。本番アプリでは、通常はパッケージマネージャーとビルドフローで導入してください。
<script type="module">
import { createEchoScan } from 'https://cdn.echoscan.org/v1/echoscan.esm.js'
const { imprint } = await createEchoScan().run()
</script>
<script src="https://cdn.echoscan.org/v1/echoscan.umd.js"></script>
<script>
window.EchoScan.createEchoScan().run().then(({ imprint }) => {
console.log(imprint)
})
</script>
サーバーへ送信
imprint は、保護対象のアクションと一緒にサーバー側コードへ届けば十分です。既存 API に合う形を選んでください。
body 方式は、業務リクエストが JSON の場合に自然です。
await fetch('/api/your-action', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...yourActionPayload,
echoscanImprint: imprint
})
})
リクエストヘッダー方式は、業務 body を変えたくない場合に使えます。
await fetch('/api/your-action', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-EchoScan-Imprint': imprint
},
body: JSON.stringify(yourActionPayload)
})
リスク判定フローを業務 API と分けたい場合は、自分のサーバー側エンドポイントを作ることもできます。
await fetch('/api/echoscan/report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ imprint })
})
/api/echoscan/report はサンプルのパスであり、あなたのサーバーで実装する必要があります。EchoScan の公式エンドポイントではありません。
Lite 導入
Lite は公開用途や軽量なリスク判断を最短で動かすためのプランです。Lite key も secret key なので、サーバー環境変数、secret manager、または同等のサーバー側シークレットストアに保存してください。
Node.js
npm install @echoscan/echoscan
import { createLiteClient } from '@echoscan/echoscan'
const echoscan = createLiteClient({
apiKey: process.env.ECHOSCAN_LITE_KEY
})
export async function getEchoScanReport(imprint) {
return echoscan.getReport(imprint)
}
Go
go get github.com/echoscan/echoscan-go@latest
package main
import (
"context"
"log"
"os"
echoscan "github.com/echoscan/echoscan-go"
)
func main() {
imprint := "fp_session_xxx"
echoscanClient, err := echoscan.NewLiteClient(os.Getenv("ECHOSCAN_LITE_KEY"))
if err != nil {
log.Fatal(err)
}
report, err := echoscanClient.GetReport(context.Background(), imprint)
if err != nil {
log.Fatal(err)
}
log.Printf("lyingCount=%v", report["lyingCount"])
}
Python
pip install echoscan
import os
from echoscan import EchoScanLiteClient
imprint = "fp_session_xxx"
echoscan_client = EchoScanLiteClient(os.environ["ECHOSCAN_LITE_KEY"])
report = echoscan_client.get_report(imprint)
print(report.get("lyingCount"))
Rust
[dependencies]
echoscan = "0.2.1"
use std::env;
use echoscan::LiteClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let imprint = "fp_session_xxx";
let api_key = env::var("ECHOSCAN_LITE_KEY")?;
let echoscan = LiteClient::new(&api_key)?;
let report = echoscan.get_report(imprint).await?;
println!("{}", report["lyingCount"]);
Ok(())
}
Lite report
Lite report は、サーバーが imprint を照会したあとに返す最小限の公開結果です。リスク判断に必要な要約フィールドだけを残し、元の収集値、内部証拠、検出実装の詳細は隠します。
Lite report は「要約 + 明細」として読むのが自然です。lyingCount は強いリスクの要約、projection はモジュール単位の結果です。サーバーはこれらを使って allow、challenge、review、deny などの独自判断を返します。
通常アクセスの例:
{
"analysis": {
"browser": {
"brand": "Google Chrome",
"browser_version": "126.0.x",
"rendering_engine": "Chromium",
"browser_version_consistency_status": "PASS"
},
"os": {
"os": "Windows",
"version": "11",
"os_consistency_status": "PASS"
},
"hash": {
"accessCount": 1,
"stableHash": "stb_8f4d2c1a",
"uniqueHash": "unq_3a9b7e42"
}
},
"lyingCount": 0,
"projection": {
"navigator": {
"status": "PASS"
},
"screen": {
"status": "PASS"
},
"webgl": {
"status": "PASS"
}
}
}
疑わしいアクセスの例:
{
"analysis": {
"browser": {
"brand": "Google Chrome",
"browser_version": "126.0.x",
"rendering_engine": "Chromium",
"browser_version_consistency_status": "FAIL"
},
"os": {
"os": "Windows",
"version": "11",
"os_consistency_status": "PASS"
},
"hash": {
"accessCount": 1,
"stableHash": "stb_8f4d2c1a",
"uniqueHash": "unq_9c0f2d31"
}
},
"lyingCount": 1,
"projection": {
"navigator": {
"status": "DECEPTIVE"
},
"screen": {
"status": "PASS"
},
"webgl": {
"status": "SUSPICIOUS"
},
"webrtc": {
"status": "SUSPICIOUS"
}
}
}
より完全な Lite surface の例:
{
"analysis": {
"browser": {
"brand": "Google Chrome",
"browser_version": "126.0.x",
"rendering_engine": "Chromium",
"browser_version_consistency_status": "PASS"
},
"os": {
"os": "Windows",
"version": "11",
"os_consistency_status": "PASS"
},
"hash": {
"accessCount": 7,
"stableHash": "stb_8f4d2c1a",
"uniqueHash": "unq_3a9b7e42"
}
},
"lyingCount": 0,
"projection": {
"audio": {
"status": "PASS"
},
"canvas": {
"status": "PASS"
},
"font": {
"status": "PASS"
},
"ip-geo-timezone": {
"status": "PASS"
},
"navigator": {
"status": "PASS"
},
"screen": {
"status": "PASS",
"resolution": "1920x1080"
},
"speech": {
"status": "PASS",
"default_voice_name": "Microsoft Jenny Online"
},
"webgl": {
"status": "PASS",
"unmasked_vendor": "Google Inc. (NVIDIA)",
"unmasked_renderer": "ANGLE (NVIDIA GeForce RTX 4060)"
},
"webrtc": {
"status": "PASS"
}
}
}
フィールド説明
| フィールド | 例 | 意味 |
|---|---|---|
analysis |
{ ... } |
EchoScan が正規化したアクセス環境の要約。ログ、管理画面、リスク調査に利用できます |
analysis.browser |
{ ... } |
ブラウザの要約。ブランド、バージョン、レンダリングエンジン、バージョン整合性を含みます |
analysis.browser.brand |
Google Chrome |
検出されたブラウザブランド。Chrome、Firefox、Safari など |
analysis.browser.browser_version |
126.0.x |
検出されたブラウザバージョン |
analysis.browser.rendering_engine |
Chromium |
ブラウザのレンダリングエンジン。Chromium、WebKit など |
analysis.browser.browser_version_consistency_status |
PASS |
ブラウザバージョン関連シグナルの整合性結果。FAIL はバージョン偽装または強い不一致を示します |
analysis.os |
{ ... } |
OS の要約。OS 名、バージョン、整合性を含みます |
analysis.os.os |
Windows |
検出された OS |
analysis.os.version |
11 |
検出された OS バージョン |
analysis.os.os_consistency_status |
PASS |
OS 関連シグナルの整合性結果 |
analysis.hash |
{ ... } |
アクセス環境の識別子と再訪要約 |
analysis.hash.accessCount |
7 |
安定したアクセス環境に紐づく観測回数。継続性の参考値で、アカウントのリクエスト回数ではありません |
analysis.hash.stableHash |
stb_8f4d2c1a |
継続性、再訪、リスク関連付けに使う安定環境識別子 |
analysis.hash.uniqueHash |
unq_3a9b7e42 |
現在のアクセス環境をより細かく区別する識別子 |
lyingCount |
0 |
素早いリスク分類に使える強いリスク要約 |
projection |
{ ... } |
navigator、screen、webgl、webrtc などのモジュール単位の結果 |
projection.<module>.status |
SUSPICIOUS |
サーバー側判断に使う、そのモジュールの公開ステータス |
projection.screen.resolution |
1920x1080 |
画面解像度の要約 |
projection.speech.default_voice_name |
Microsoft Nanami |
ブラウザの既定音声名の要約 |
projection.webgl.unmasked_vendor |
Google Inc. |
WebGL グラフィックベンダーの要約 |
projection.webgl.unmasked_renderer |
ANGLE |
WebGL レンダラーの要約 |
ステータス説明
| status | 意味 | よくある処理 |
|---|---|---|
PASS |
現在のモジュールで明確な異常は見つかっていません | 通常は許可 |
SUSPICIOUS |
不審または低信頼のシグナルがあります | 追加認証、観察、リスクスコア加算 |
DECEPTIVE |
強い偽装または不一致シグナルがあります | 追加認証、レビュー、拒否 |
ポリシーコードでは旧値 WARN と FAIL との互換性を維持できます。
サーバー側の判断
サーバーが report を受け取ったら、一般的には allow、challenge、review、deny などの最小限の判断結果に変換し、その結果をブラウザへ返します。
これらの判断は、業務リスク、誤判定コスト、ユーザー体験に応じてサーバー側で実装します。よくある処理は次のとおりです。
| decision | よくある処理 |
|---|---|
allow |
このリクエストを許可し、登録、ログイン、購入などの業務処理を続行します |
challenge |
CAPTCHA、SMS、メール認証、二段階確認などの追加確認を求めます |
review |
人手レビュー、バックオフィスキュー、または遅延処理に回します |
deny |
このリクエストを拒否し、保護対象の業務処理を続行しません |
下のコードは最小判断の例です。実際のルールは、業務リスク、誤判定コスト、ユーザー体験に合わせて調整できます。完全な report は、必要に応じてサーバーログ、管理画面、リスク管理基盤に保存してください。
const riskStatuses = new Set([
'SUSPICIOUS',
'DECEPTIVE',
'WARN',
'FAIL'
])
const hasStrongRisk = report.lyingCount > 0
const hasRiskStatus = Object.values(report.projection ?? {}).some((module) =>
riskStatuses.has(module?.status)
)
const decision = hasStrongRisk || hasRiskStatus
? 'challenge'
: 'allow'
return Response.json({ decision })
Pro 導入
Pro でもブラウザ imprint とサーバー側 secret key の境界は同じです。より高度なリスクポリシーと運用分析に向いています。
- Lite と比べて、Pro は Bot、IP / ネットワークリスク、履歴アクセス分析のシグナルがより豊富です
- Pro はルール設計、帰因分析、社内ダッシュボード向けに、より詳細なモジュール観測値を返します
- Pro の履歴照会は
daysまたはfrom/toの時間窓を指定でき、summaryとtimelineを返します
Node.js
npm install @echoscan/echoscan
import { createProClient } from '@echoscan/echoscan'
const echoscan = createProClient({
apiKey: process.env.ECHOSCAN_PRO_KEY
})
const report = await echoscan.getReport(imprint)
const historyByDays = await echoscan.getHistory(imprint, { days: 7 })
const historyByRange = await echoscan.getHistory(imprint, {
from: '2026-03-01',
to: '2026-03-18'
})
Go
go get github.com/echoscan/echoscan-go@latest
package main
import (
"context"
"log"
"os"
echoscan "github.com/echoscan/echoscan-go"
)
func main() {
imprint := "fp_session_xxx"
days := 7
echoscanClient, err := echoscan.NewProClient(os.Getenv("ECHOSCAN_PRO_KEY"))
if err != nil {
log.Fatal(err)
}
report, err := echoscanClient.GetReport(context.Background(), imprint)
if err != nil {
log.Fatal(err)
}
history, err := echoscanClient.GetHistory(context.Background(), imprint, echoscan.HistoryQuery{
Days: &days,
})
if err != nil {
log.Fatal(err)
}
_, _ = report, history
}
Python
pip install echoscan
import os
from echoscan import EchoScanProClient
imprint = "fp_session_xxx"
echoscan_client = EchoScanProClient(os.environ["ECHOSCAN_PRO_KEY"])
report = echoscan_client.get_report(imprint)
history = echoscan_client.get_history(imprint, days=7)
print(report.get("lyingCount"), history.get("summary"))
Rust
[dependencies]
echoscan = "0.2.1"
use std::env;
use echoscan::{HistoryQuery, ProClient};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let imprint = "fp_session_xxx";
let api_key = env::var("ECHOSCAN_PRO_KEY")?;
let echoscan = ProClient::new(&api_key)?;
let report = echoscan.get_report(imprint).await?;
let history = echoscan
.get_history(imprint, HistoryQuery::Days { days: 7, recent: None })
.await?;
println!("{} {}", report["lyingCount"], history["summary"]);
Ok(())
}
Pro report
{
"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"
},
"ip": {
"status": "PASS"
},
"hash": {
"accessCount": 31,
"calculatedAt": "2026-03-19T10:27:25+09:00",
"stableHash": "stb_8f4d2c1a",
"uniqueHash": "unq_3a9b7e42"
},
"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"
}
}
}
}
Pro history
{
"imprint": "fp_session_...",
"range": {
"from": "2026-03-01",
"to": "2026-03-18"
},
"recent": 20,
"summary": {},
"timeline": []
}
daysとfrom/toは排他ですfromとtoは必ずセットで指定します- 日付形式は
YYYY-MM-DD固定です
エラー構造
{
"code": "auth_failed",
"httpStatus": 401,
"message": "Authentication failed",
"requestId": "req_...",
"retryable": false
}
分岐には code を使い、message は表示テキストとして扱ってください。
API Key とセキュリティ境界
- EchoScan Console にログインし、API Keys ページで Lite または Pro key を作成します。
- プレーンテキストの key は作成時に一度だけ表示されます。すぐにサーバー環境変数または secret manager に保存してください。
- EchoScan secret key をブラウザコード、フロントエンド環境変数、localStorage、ログ、git、公開ファイルに置かないでください。
- ブラウザは
imprintを生成して送信します。report 照会と最終的なリスク判断はサーバー側で行います。 - 導入・技術サポート:
support@echoscan.org - プライバシー・セキュリティ関連:
security@echoscan.org
AI コーディングツール
Claude、Cursor、Codex などの AI コーディングツールに EchoScan を導入させる場合は、先に次の文書を読ませてください。
https://echoscan.org/llms.txthttps://echoscan.org/docs/ai-context.md
これらのファイルは、このページと同じドキュメント事実ソースから生成されます。AI ツールが読めない場合は、EchoScan API コンテキストを確認できないことを明示して停止し、パッケージ名、フィールド、導入パスを推測しないでください。