888desturl 是一個用來追蹤網址最終目的地的工具,基於 Node.js、Fastify 與 Playwright(Headless Chromium)建構。它不只追蹤傳統 HTTP 3xx,還能處理 meta refresh 與 JavaScript 導向,現在也支援:
- 靜態轉址網址自動解包 (YouTube, Facebook, Google, Slack) 以加速追蹤並避免機器人阻擋
- YouTube 中介警告頁面("Are you sure you want to leave YouTube?")自動點擊繞過機制
- final-only Google Web Risk 檢查
- final 頁面截圖預覽
- 每次 trace 的獨立結果頁
- 可分享的結果頁 metadata 與結果頁連結複製
- 7 天預覽圖保留與自動清理
- browser localStorage 最近查詢紀錄
- SQLite server history / usage stats
- admin login 與 admin dashboard
https://url.david888.com
- Backend: Node.js, Fastify, Playwright
- Storage: SQLite
- Frontend: HTML, Vanilla JavaScript, Tailwind CSS via CDN
- Deployment: Docker, Docker Compose
複製 .env.example 成 .env,再填入你的設定值:
cp .env.example .env必要欄位:
GOOGLE_WEB_RISK_API_KEYADMIN_USERNAMEADMIN_PASSWORD
建議欄位:
DATA_DIR=./dataPREVIEW_RETENTION_DAYS=7HISTORY_RETENTION_DAYS=90
npm install這一步會安裝 playwright 與 sqlite3。
npx playwright install chromiumnpm startOpen http://localhost:3000.
Build and run:
docker compose up -d --buildStop:
docker compose downCurrent docker-compose.yml behavior:
- loads variables from
.env - mounts
./datato/app/data - keeps preview images and SQLite data outside the container layer
Example:
PORT=3000
HOST=0.0.0.0
DATA_DIR=./data
PREVIEW_RETENTION_DAYS=7
HISTORY_RETENTION_DAYS=90
GOOGLE_WEB_RISK_API_KEY=replace-with-your-key
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-this-password
ADMIN_SESSION_TTL_HOURS=24Notes:
.envis ignored by git.envis excluded from Docker build context- preview images are stored under
DATA_DIR/previews - SQLite database is stored under
DATA_DIR/history.sqlite
Full redirect diagnostics plus final-only security check and final-image preview URL.
Query:
url: required fullhttp://orhttps://URLcontext: optional, supportsline
Response highlights:
{
"final_url": "https://example.com/final",
"input_url": "https://example.com/start",
"result_id": "AbCdEf123456",
"result_url": "https://url.david888.com/result/AbCdEf123456",
"redirect_count": 2,
"preview_url": "/previews/2026/05/30/abcd1234.jpg",
"final_image_url": "/previews/2026/05/30/abcd1234.jpg",
"security": {
"status": "safe",
"source": "google_webrisk",
"checked_url": "https://example.com/final",
"checked_at": "2026-05-30T08:00:00.000Z",
"message": "No Google Web Risk match was found for the final destination.",
"threat_types": []
},
"chain": []
}If the browser UI calls this endpoint, it sets header x-888desturl-client: web. Other callers are stored as api traffic in server history by default.
Final destination only.
Query:
url: required fullhttp://orhttps://URLformat: optional, defaulttext, supportsjsoncontext: optional, supportsline
format=json also includes:
result_idresult_urlpreview_urlfinal_image_urlsecurity
Short CLI alias for /api/final.
Public result lookup for one previously recorded trace result.
Use this when:
- you want to render a standalone result page
- you want to revisit one trace later
- you want a shareable detail URL without re-running the trace
Response includes:
result_idresult_urlcreated_atinput_urlfinal_urlpreview_urlfinal_image_urlsecuritysecurity_statuschain
Compatibility note:
security_status,security_message,security_checked_url, andthreat_typesare still returned for existing clients- new clients should prefer the nested
securityobject
Public final-image lookup for one stored trace result.
Response includes:
result_idavailablestatusfinal_image_urlimage_urlmime_type
If the trace result still exists but the preview image has already expired, this endpoint returns available: false and status: "unavailable".
Public Web Risk lookup result for one stored trace result.
Response includes:
result_idsecurity
Health check:
{
"ok": true,
"storage_enabled": true,
"web_risk_enabled": true
}Admin page:
GET /admin
Admin APIs:
GET /api/admin/sessionPOST /api/admin/loginPOST /api/admin/logoutGET /api/admin/statsGET /api/admin/history
Security behavior:
- login is controlled by
ADMIN_USERNAMEandADMIN_PASSWORD - login attempts are limited to 3 per 5 minutes per IP
- authenticated admin access uses an HttpOnly cookie session
Current limitation:
- admin sessions are stored in memory
- restarting the service logs out admin users
- multi-instance deployments would need shared session storage later
Every stored trace result now gets a stable result_id.
Public result URLs:
GET /result/:resultIdGET /r/:resultId
Behavior:
- the page reads data from
GET /api/results/:resultId - the result page includes shareable metadata for social previews
- the result page can copy its own standalone URL
- admin history links directly to the standalone result page
- preview images may disappear after the preview retention window
- the result row itself remains available until history retention removes it
- if the history record expires, the result page returns not found
- preview screenshots: 7 days by default
- server history: 90 days by default
- cleanup runs at startup and every 12 hours
When a preview expires:
- the image file is deleted
- the history row remains, but
preview_urlis cleared
├── .env.example
├── CHANGELOG.md
├── Dockerfile
├── docker-compose.yml
├── lib/
│ ├── admin-auth.js
│ ├── env.js
│ └── storage.js
├── package.json
├── public/
│ ├── admin.html
│ ├── index.html
│ └── result.html
└── server.js


