AntiDetect
Funzionalità Tecnologia Prezzi Per chi è
Docs Blog FAQ
Lingua
EnglishItalianoDeutschEspañolРусский
Scarica

La tua lista di font è una confessione sul sistema operativo

Nessuna API dice a un sito quali font hai installato. Li misura invece — disegnando testo e confrontando larghezze, qualche centinaio di volte, in meno di cinquanta millisecondi. Il risultato porta circa quattordici bit, e contraddirà senza esitazione uno user agent falsificato.

Misurazione, non enumerazione

Non è mai esistita una web API che restituisca l'elenco dei font installati. Non ce n'è mai stato bisogno, perché misurare funziona quasi altrettanto bene e non richiede alcun permesso.

La tecnica è la stessa usata all'incirca dal 2007. Renderizza una stringa in un font di fallback noto e registra la larghezza. Poi renderizza la stessa stringa chiedendo per primo il font candidato, con lo stesso fallback dietro. Se la larghezza cambia, il candidato esiste ed è stato usato. Se non cambia, il candidato manca e ha disegnato di nuovo il fallback.

const span = document.createElement('span');
span.style.cssText = 'position:absolute;left:-9999px;font-size:72px';
span.textContent = 'mmmmmmmmmmlli';

span.style.fontFamily = 'monospace';
document.body.appendChild(span);
const base = span.offsetWidth;

span.style.fontFamily = '"Segoe UI", monospace';
const installed = span.offsetWidth !== base;

La stringa di test non è casuale. mmmmmmmmmmlli mescola i glifi più larghi e più stretti della maggior parte dei caratteri latini, massimizzando la differenza di larghezza fra due font qualsiasi. A 72 pixel la differenza è impossibile da non vedere.

Esegui tutto questo su un elenco di due o trecento candidati e hai il profilo dei font. Costa qualche decina di millisecondi e non lascia traccia in nessuna richiesta di permesso.

La stessa stringa di test renderizzata in due caratteri, con le larghezze misurate sotto
L'intera tecnica. Renderizza la stringa nel font candidato con un fallback noto dietro: se la larghezza si muove, il font è installato.

Perché i font identificano il sistema operativo

Gli insiemi di font non sono casuali. Arrivano con il sistema operativo, e ogni piattaforma ne distribuisce uno caratteristico.

FontDistribuito conCosa significa la sua presenza
Segoe UIWindows Vista e successiviWindows, quasi con certezza
Segoe UI VariableWindows 11Distingue 11 da 10
Helvetica NeuemacOSPiattaforma Apple
Ubuntu, Liberation SansDistribuzioni Linux diffuseLinux
Calibri, CambriaMicrosoft OfficeOffice installato; debole segnale di Windows
Arial, Times New RomanQuasi ovunqueNiente

È il controllo che smaschera gratis uno user agent falsificato. Un profilo che dichiara Windows 11 e non riesce a renderizzare Segoe UI Variable si è contraddetto in un solo confronto di offsetWidth — nessun dato esterno, nessun database di reputazione, nessun machine learning.

L'errore inverso è altrettanto comune e più difficile da vedere: un profilo che dichiara macOS su un host Windows, dove il Segoe UI dell'host è ancora installato e misurabile. Lo user agent dice Mac; i font dicono Windows; vincono i font.

Quanto vale

Il lavoro di Panopticlick della EFF ha stimato gli elenchi di font intorno a 13,9 bit di informazione identificativa — sufficienti da soli a restringere un browser a uno su circa quindicimila. È fra i valori più alti per un singolo segnale in tutta la letteratura sul fingerprinting, sopra la risoluzione dello schermo e ben sopra la stringa dello user agent.

Due avvertenze per restare onesti. Primo, quella cifra viene da una popolazione auto-selezionata di utenti interessati alla privacy e sovrastima l'entropia del web generale. Secondo, sta calando: Windows 11, le versioni recenti di macOS e le distribuzioni Linux più diffuse distribuiscono set predefiniti sempre più simili, e i web font hanno tolto quasi ogni motivo di installarne altri.

Quel che sopravvive al calo è la parte che qui conta. Anche se l'elenco dei font non identifica più una macchina in modo univoco, identifica comunque la piattaforma — e l'identificazione della piattaforma è ciò che smonta un profilo incoerente.

Gli altri modi di chiedere

La misurazione della larghezza è il metodo classico, non l'unico. Un'implementazione che aggancia solo offsetWidth si perderà questi.

measureText del canvas

ctx.measureText() restituisce un oggetto TextMetrics con la larghezza di avanzamento sub-pixel e, nei browser moderni, l'ascendente e il discendente reali del riquadro di ingombro. È più preciso della misurazione sugli elementi e vive nell'API canvas, quindi può girare dentro un OffscreenCanvas in un worker, dove gli hook a livello di pagina non arrivano.

Solo CSS

Il rilevamento dei font si può fare senza alcun JavaScript, usando @font-face con unicode-range e una richiesta di immagine di sfondo che parte solo quando viene usato un certo fallback. Nessuno script da agganciare, nessuna API da sovrascrivere.

Local Font Access

Chrome 103 ha introdotto window.queryLocalFonts(), che restituisce direttamente l'elenco completo dei font locali — dietro una richiesta di permesso all'utente. In pratica gli script di fingerprinting non la usano, proprio perché chiede il permesso. Vale la pena conoscerla soprattutto perché un browser che dichiara Chrome 147 dovrebbe avere l'API presente, e un profilo che l'ha rimossa ha creato una nuova incoerenza.

Farlo nel modo giusto

Funzionano due approcci, e uno molto comune no.

Cosa non funziona: restituire un elenco vuoto o minimo. Un browser con cinque font è più notevole di uno con duecento. È lo stesso errore della randomizzazione del canvas: hai sostituito un valore comune con uno raro e l'hai chiamato privacy.

Primo approccio: distribuire il set giusto. Il profilo dichiara Windows 11, quindi l'elenco dei font è quello predefinito di Windows 11, presente e misurabile. È pienamente realizzabile solo quando lo stack dei font è sotto controllo — il browser deve risolvere le richieste di font su un set dichiarato invece che su quello installato sull'host. È una questione a livello di engine, ed è per questo che è una delle cose più difficili da aggiungere a posteriori.

Secondo approccio: non dichiarare una piattaforma su cui non sei. Esegui i profili Windows su Windows e quelli Mac su Mac. Poco glamour, del tutto efficace e gratis. Se puoi scegliere l'host, è la risposta corretta più economica a disposizione.

Qualunque strada tu prenda, vale il vincolo dell'articolo sulla coerenza: il set di font deve concordare con lo user agent, con il renderer WebGL e con la stringa della piattaforma. I font sono semplicemente i più economici dei quattro da verificare, ed è per questo che vengono verificati per primi.

Controllare il proprio

Il test più rapido è una singola sonda contro il sistema operativo che dichiari. Incolla questo nella console di un profilo e leggi la risposta:

function has(f) {
  const s = document.createElement('span');
  s.style.cssText = 'position:absolute;left:-9999px;font-size:72px';
  s.textContent = 'mmmmmmmmmmlli';
  document.body.appendChild(s);
  s.style.fontFamily = 'monospace';       const base = s.offsetWidth;
  s.style.fontFamily = `"${f}", monospace`; const w = s.offsetWidth;
  s.remove();
  return w !== base;
}
console.log({
  windows: has('Segoe UI'),
  win11:   has('Segoe UI Variable'),
  macos:   has('Helvetica Neue'),
  linux:   has('Ubuntu')
});

Esattamente uno di questi dovrebbe risultare vero, e dev'essere quello che corrisponde al tuo user agent. Due valori veri significano che il tuo profilo indossa due sistemi operativi insieme. Per un quadro più completo, browserleaks.com/fonts e CreepJS enumerano entrambi il set completo e, nel caso di CreepJS, ti dicono a chiare lettere quando l'elenco non concorda con la piattaforma che dichiari.

Set di font che corrispondono alla macchina

P8 distribuisce ogni profilo con il set di font predefinito della versione di sistema operativo che dichiara — non i font dell'host con sopra uno user agent diverso.

Inizia gratis
Tutti gli articoli Prossimo: perché gli account pubblicitari vengono bannati davvero