fingerprintd
documentation

Documentation

Le panel sert des fingerprints déjà collectés. Le collecteur tourne en continu et, quand un job attend, il va chercher ce pattern en priorité.

Connexion

Un seul token protège le panel et l'API. Il se trouve dans /etc/fingerprintd/config.json (clé server.token). La session est un cookie signé, HttpOnly et Secure, valable 24 h.

Pour partager l'accès, transmets l'URL et le token. Pour révoquer, change le token puis systemctl restart fingerprintd : toutes les sessions tombent.

Jobs de pull

Un job réserve N profils sur un pattern (plateforme, pays). Chaque pull en sort un, sans jamais répéter le même profil dans ce job. L'état est persistant : un redémarrage ne redistribue pas un profil déjà tiré.

Créer

curl -s -X POST -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"Windows FR","total":50,"pattern":{"tags":["Windows"],"country":"fr"}}' \
  https://VOTRE-HOTE/v1/jobs

Tirer

curl -s -X POST -H "X-API-Key: $TOKEN" \
  https://VOTRE-HOTE/v1/jobs/<id>/pull | jq '.fingerprint'

La réponse contient fingerprint (l'objet complet), meta (id, pays, tags, date) et job (avancement).

États

ChampSignification
served / totalprogression du job
statusactive, completed (tous tirés) ou cancelled
availableprofils du pool qui matchent le pattern et n'ont pas encore été servis à ce job
waitingtrue quand available < remaining : le collecteur doit approvisionner
next_attempt_atprochaine tentative après une indisponibilité de la source
last_errordernière erreur d'approvisionnement (ex. 503)

Pool

La page /pool liste les profils collectés et permet de les filtrer, de les prévisualiser et de les télécharger. Un téléchargement retire les profils du pool : ils sont marqués « déjà tirés » et ne seront plus servis, ni par l'API, ni par les jobs.

Filtres

Combinaison libre : pays, plateforme, navigateur, mode, largeur et hauteur minimales, version navigateur minimale, et recherche texte dans le user agent. Les valeurs affichées sont celles réellement détectées dans le profil (plateforme, navigateur déduit de l'UA, écran, WebGL), pas celles demandées à la source.

Formats

FormatContenu
jsonl (défaut)un objet fingerprint complet par ligne — le plus simple à consommer en script
txtfiche lisible par profil (id, plateforme, écran, WebGL, UA…)
jsontableau JSON de tous les profils
csvtableur : id, pays, plateforme, navigateur, écran, matériel, WebGL, UA, date

API

# lister (métadonnées + attributs), filtres multiples
curl -s -H "X-API-Key: $TOKEN" \
  "https://VOTRE-HOTE/v1/pool?platform=Windows&min_width=1920&browser=Chrome&limit=50"

# un profil complet
curl -s -H "X-API-Key: $TOKEN" https://VOTRE-HOTE/v1/pool/<id>

# télécharger 100 profils filtrés et les sortir du pool
curl -s -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"format":"jsonl","filter":{"platform":"Windows"},"limit":100}' \
  https://VOTRE-HOTE/v1/pool/download -o profils.jsonl

Le corps accepte ids (sélection explicite) ou filter + limit, et "consume": false pour télécharger sans sortir les profils du pool. Limite : 1000 profils par téléchargement.

HQ

La page /hq filtre le pool pour ne garder que les profils ultra cohérents : Chrome desktop uniquement, version/build/marques GREASE cohérents, WebGL et WebGPU du même fabricant, écran et barre des tâches plausibles, matériel standard, et couple pays ↔ fuseau ↔ langue valide.

La référence par version (build médian, marque GREASE majoritaire) est calculée à partir du pool lui-même, pas d'une table externe. L'analyse affiche le taux de profils retenus, la répartition par plateforme et le décompte des raisons de rejet.

# rapport HQ
curl -s -H "X-API-Key: $TOKEN" \
  "https://VOTRE-HOTE/v1/hq?platform=Windows&min_major=150"

# export des profils retenus
curl -s -H "X-API-Key: $TOKEN" -H "Content-Type: application/json" \
  -d '{"platform":"Windows","major":156,"drop_voices":true}' \
  https://VOTRE-HOTE/v1/hq/download -o hq.jsonl

consume: true retire les profils exportés du pool ; par défaut ils y restent. drop_voices retire speechSynthesis (champ peu fiable chez ce fournisseur). Une sortie de plus de 100 profils exige "confirm": true dans le corps.

La page liste aussi les profils HQ avec les mêmes fonctions que le pool : filtres, pagination, aperçu, copie, téléchargement par ligne, par sélection ou par filtres, et formats txt, jsonl, json, csv.

Priorité d'approvisionnement

Tant qu'un job attend des profils, le collecteur consacre ses requêtes à son pattern avant le pattern par défaut de la configuration. Plusieurs jobs en attente sont servis à tour de rôle (le moins récemment approvisionné d'abord).

Si la source ne fournit pas ce pattern (par exemple ERROR_FINGERPRINT_SERVICE_UNAVAILABLE — l'API n'a pas de profils iOS ou macOS à un instant donné), le job passe en backoff : 30 s, 1 min, 2 min… jusqu'à 10 min. Entre deux tentatives, la collecte par défaut reprend, donc le pool continue à se remplir. Le job reste waiting et l'interface affiche l'erreur et le délai : source indisponible (503) · nouvel essai dans 27 s, avec le code complet en infobulle.

Quand l'échec est global (clé refusée, ou plusieurs erreurs consécutives), un bandeau en haut du panel reprend le code HTTP, le message et l'heure de la prochaine tentative. Les mêmes données sont disponibles dans /stats et /metrics.

À retenir : tous les tags ne sont pas disponibles en permanence chez le fournisseur. Windows, Android et Linux répondent, iOS et macOS renvoient régulièrement un 503.

API HTTP

Toutes les routes exigent le token : X-API-Key: <token>, Authorization: Bearer <token> ou ?token=<token> (ou le cookie de session pour le panel).

RouteRôle
GET /v1/fingerprintun profil ; filtres country, tag, mode, raw=1
GET /v1/batch?n=10plusieurs profils d'un coup
GET /v1/export?limit=100export JSONL
GET /v1/poolprofils du pool (filtres multiples, pagination)
GET /v1/hqrapport de qualité HQ (retenus, rejets, référence)
POST /v1/hq/downloadexport des profils HQ (JSONL)
GET /v1/pool/<id>un profil complet
POST /v1/pool/downloadtélécharger (txt/jsonl/json/csv) et sortir du pool
GET /v1/jobsliste des jobs avec leur état d'approvisionnement
POST /v1/jobscréer un job
GET /v1/jobs/<id>un job
POST /v1/jobs/<id>/pulltirer le profil suivant
POST /v1/jobs/<id>/cancelannuler
DELETE /v1/jobs/<id>supprimer
GET /stats · GET /metricsétat détaillé · métriques Prometheus
# filtrer sur la plateforme réelle
curl -s -H "X-API-Key: $TOKEN" \
  "https://VOTRE-HOTE/v1/fingerprint?tag=Windows&country=de&raw=1"

Codes d'erreur : 401 unauthorized, 400 unknown_parameter, 404 pool_empty, 409 job_finished, 409 pool_exhausted, 429 rate_limited.

Format des profils

La collecte utilise le format raw de l'API, le seul qui contient le profil complet : fonts (polices installées), canvas, visitor_id, audio, systemfonts, plugins, headers… Le format chromium (12 clés) est une projection normalisée qui n'expose pas ces champs.

Les profils raw sont projetés pour l'interface (plateforme, navigateur, écran, cœur/RAM, fuseau) et le filtre HQ s'applique dessus. Deux contrôles HQ ne sont pas applicables au raw, car l'API y masque les valeurs correspondantes : la liste complète des marques UA-CH (brandFullVersionList) et le couple vendor/renderer WebGL non masqué (donc les vérifications GPU Direct3D11/Metal, vendor = renderer et WebGPU = même fabricant). Les autres règles (version/build/GREASE, OS, écran, DPR, barre des tâches, cœur/RAM, pays ↔ fuseau ↔ langue) restent actives.

Le format de collecte se change dans /etc/fingerprintd/config.json : "format": "raw" ou "chromium", puis redémarrage du service.

L'analyse HQ est mise en cache par profil et recalculée en tâche de fond (par défaut toutes les 5 minutes, réglable via hq.refresh_minutes). Une requête ne réévalue jamais tout le pool : elle lit les verdicts stockés, ce qui la rend instantanée. Un profil déjà jugé garde son verdict ; seuls les nouveaux profils sont évalués au cycle suivant. La référence par version est persistée (hq-ref.json) pour rester stable entre deux redémarrages.

Les profils collectés avant le passage en raw (format chromium) sont marqués d'un drapeau orange incomplet dans la colonne État : ils n'ont ni fonts ni canvas, et cette donnée ne peut pas être récupérée après coup. Le filtre Format → incomplet les isole ; l'aperçu affiche « incomplet — collecté avant le raw ».

Filtres

Un seul tag à la fois : l'API ne combine pas les tags de façon fiable. Un tag OS (Windows, macOS, Linux, Android, iOS), un pays ISO-2, éventuellement mode (random ou generate).

La plateforme réellement détectée est stockée comme tag : ?tag=Windows filtre donc ce que le profil est, pas ce qui a été demandé.

CLI

fingerprintd get --tag Windows --country fr   # depuis le pool (gratuit)
fingerprintd get --live                      # requête à l'API (facturée)
fingerprintd stats
fingerprintd export --out pool.jsonl --limit 500
fingerprintd keygen                          # nouvelle clé de chiffrement

Chiffrement et sécurité

Le pool et les jobs sont chiffrés au repos en AES-256-GCM, clé dans /etc/fingerprintd/secret.key (hors du répertoire de données). Sans la clé, le service refuse de démarrer.

Côté réseau : TLS public, HSTS, cookie Secure, rate limit par IP (30 req/s, login 5 essais/min), validation stricte des paramètres et protection CSRF sur les mutations.

Dépannage

  • 401 : token absent ou faux ; en-tête X-API-Key oublié ?
  • 404 pool_empty : aucun profil ne matche encore ; attends la collecte ou vérifie le pattern.
  • 409 pool_exhausted : tous les profils correspondants ont déjà été servis à ce job ; le collecteur en ajoute.
  • 429 : trop de requêtes ou trop de tentatives de login depuis cette IP.
  • Job bloqué à 0 : regarde waiting / last_error. Un 503 signifie que le fournisseur n'a pas ce pattern pour l'instant.

Journaux : journalctl -u fingerprintd -f pour le service, /var/log/caddy/panel.log pour les accès HTTP.