Advanced SDK
noscript beacon
When JavaScript is disabled, the snippet never loads. The noscript beacon catches these cases:
<script type="module">
const mod = await import('https://cdn.shieldlabs.ai/snippet.js?publicKey=YOUR_PUBLIC_KEY');
mod.checkAnonymous();
</script>
<noscript>
<img
src="https://rest.shieldlabs.ai/noscript?publicKey=YOUR_PUBLIC_KEY"
width="1" height="1"
style="display:none" alt=""
>
</noscript>
| Field | Value |
|---|
| Score | 90 |
| Details | JavaScript disabled (WebRTC) or similar |
| UserHID | empty / anonymous |
| DeviceID, VisitorID | zero UUIDs |
| Webhook | Fires if callback URL is configured |
noscript checks consume request weight like normal fingerprint checks.
Add img-src https://rest.shieldlabs.ai to your CSP if you use the noscript beacon.
Hashing user IDs
Never pass raw user IDs, emails, or phone numbers to checkAuthenticatedUser().
async function hashUserId(userId) {
const encoder = new TextEncoder();
const data = encoder.encode(String(userId));
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
const hashedId = await hashUserId(currentUser.id);
mod.checkAuthenticatedUser(hashedId);
Force check patterns
forceCheck* clears sessionStorage and always sends a fresh fingerprint:
document.getElementById('checkout-btn').addEventListener('click', async (e) => {
e.preventDefault();
const mod = await import(`https://cdn.shieldlabs.ai/snippet.js?publicKey=${PUBLIC_KEY}`);
mod.forceCheckAuthenticatedUser(userHashedId, async (ip, requestId) => {
const response = await fetch('/api/initiate-checkout', {
method: 'POST',
body: JSON.stringify({ requestId }),
});
if (response.ok) window.location.href = '/checkout';
});
});
SPA and route changes
Call the SDK once on app initialization. Re-check only when the authenticated user changes:
useEffect(() => {
(async () => {
const mod = await import(`https://cdn.shieldlabs.ai/snippet.js?publicKey=${PUBLIC_KEY}`);
if (user) {
mod.checkAuthenticatedUser(await hashUserId(user.id));
} else {
mod.checkAnonymous();
}
})();
}, [user?.id]);
Do not call on every route change unless you intentionally want multiple billable checks.
Port scanning
On Chromium only, the snippet loads portscanner.js and probes localhost ports for antidetect/automation tools. Firefox and Safari skip port scan — TCP OS and STUN signals still apply.
Module caching
Browser import() caches the module URL. Safe to import in multiple places.
WebRTC note
The snippet may POST to /session/{id}/trickle for ICE candidates. Shield.Core uses no-trickle ICE gathering — these requests may 404 without affecting scoring.