Back to Knowledge Hub
Fingerprint

CreepJS Intl Report: Fields and Missing Values

Trace CreepJS Intl fields to their fixed inputs, locale collection and error paths, without treating formatting differences as identity or a lie verdict.

BotBrowser Team

Documentation

Want the structured docs for Fingerprint?

This article lives in the editorial library. For step-by-step setup, reference material, and ongoing updates, jump into the docs section.

A CreepJS Intl report combines formatted samples, a condensed locale list and an inherited assessment. Those values have different sources: a missing line is not necessarily an unavailable API, and a changed phrase is not itself a finding of modification. BotBrowser supports timezone, locale and language configuration; it does not guarantee a particular CreepJS classification or identical locale-data output across browser builds. Correct interpretation starts with the call that produced each field, including its options and failure path.

TL;DR

  • The pinned Intl collector returns six formatting samples plus a locale string. It does not run seven copies of the same locale test.
  • Constructor-locale collection uses no arguments, skips exceptions and removes duplicates. The resulting string loses the mapping between constructors and locales.
  • DisplayNames needs options. Its no-argument locale attempt can be skipped even when the separately configured display-name sample works.
  • Sample callback failures become undefined; an outer collector failure and the renderer's htmlElementVersion guard follow different paths.
  • lied consumes existing resolvedOptions concerns. It is not computed by comparing the six formatted strings with a reference device.

Contents

Source-flow diagram separates six fixed-input formatters, deduplicated constructor locales, inherited resolvedOptions concerns and the htmlElementVersion display guard.

Seven values, six formatting calls

CreepJS revision 10aa6724cd33a1015db1574211890518cd04f0cc defines the relevant collector in src/intl/index.ts. Its returned object names dateTimeFormat, displayNames, listFormat, numberFormat, pluralRules, relativeTimeFormat, locale and lied. The first six are formatted results. The seventh visible value, locale, comes from a separate constructor loop. The assessment is another property, not an eighth formatted sentence. Preserving these categories prevents a report label from being mistaken for the API call itself. The CreepJS timezone field comparison separates the resolved identifier from historical candidate reduction and two current-date offset paths; those timezone producers are distinct from these formatted Intl samples.

The date sample formats the fixed numeric timestamp 963644400000, requesting a long month and a long time-zone name. It does not supply an explicit locale or time zone. The timestamp is an input chosen by the source, not the time at which the visitor opened the detector. MDN documents that DateTimeFormat.format() accepts a date or timestamp and that formatting can vary across implementations. A month or zone label therefore needs its formatter context before it can support a comparison.

The display-name sample uses new Intl.DisplayNames(undefined, { type: 'language' }).of('en-US'). Here en-US is the language tag being named; it is not the locale explicitly requested for the naming language. The first argument is undefined, leaving default locale resolution in use. A translated name for English in the report should not be relabeled as the visitor's declared preferred language. Input language and output language occupy different positions in this call.

The list sample formats the two strings ['0', '1'] with style: 'long' and type: 'disjunction'. The number sample formats 21000000 with compact notation and a long compact display. Those options intentionally select language-dependent expressions. A change in conjunction, abbreviation or spacing can be a change in formatting data rather than the underlying numeric input. The table separates the options and input types that produce list punctuation and compact-number wording.

Returned fieldSource call or fixed inputInformation retained by the field
dateTimeFormat963644400000; long month and zone nameA date-format sample using default locale and zone
displayNamestype: 'language'; .of('en-US')A localized display name for that language tag
listFormat['0', '1']; long disjunctionA formatted two-item list
numberFormat21000000; compact, long displayA compact number-format sample
pluralRules.select(1) with default optionsA plural-category label, not a formatted number
relativeTimeFormat1, 'year'; best-fit, automatic numeric wording, long styleA relative-time phrase
localeSuccessful constructor resolvedOptions().locale readsA deduplicated string without constructor labels

PluralRules().select(1) returns a category associated with the supplied number, while RelativeTimeFormat(...).format(1, 'year') produces language-dependent relative wording. Neither reads the current year from a clock. The explicit numeric: 'auto' option permits a lexical phrase when the locale has one; it does not require every locale to express the result with a digit. The Intl formatting guide covers application-level locale selection and fallback, a separate task from tracing these detector fields.

Constructor locales and lost provenance

The helper named getLocale tries seven constructors in order: Collator, DateTimeFormat, DisplayNames, ListFormat, NumberFormat, PluralRules and RelativeTimeFormat. Each attempt calls the constructor without arguments, reads resolvedOptions().locale, and appends the value if that sequence completes. A try/catch surrounds each attempt. An exception returns the accumulated list unchanged; it does not append a named failure marker. The collector subsequently removes duplicates with Set.

This operation is not a per-constructor diagnostic table. Suppose, as a hypothetical interpretation case, several successful constructors resolve to the same locale. The deduplicated result contains that locale once, regardless of how many constructors produced it. If two constructors resolve differently, the result preserves distinct values in insertion order, but not the association between a particular constructor and its value. The returned '' + locale then converts the array into a string. These are source-defined transformations, not an observed browser capture.

DisplayNames exposes a concrete distinction between constructor requirements and capability. MDN specifies a required options argument with a type. The helper's no-argument construction can therefore throw even on an implementation that supports a properly configured Intl.DisplayNames. The helper skips that attempt. In contrast, the separate displayNames sample supplies type: 'language'. Successful support for that sample is compatible with the locale helper omitting the constructor; the two calls did not ask the same question.

Collator creates the opposite-looking asymmetry. It participates in the constructor-locale loop, but the six formatted samples contain no collation comparison. Its presence in the renderer's constructor tooltip does not mean that two strings were sorted or compared by this module. A report reader can establish that the source requested its resolved locale; a collation accuracy or ordering result would require a different operation. This distinction keeps the tooltip from becoming an invented test inventory.

The aggregate locale string also differs from navigator.languages and the HTTP Accept-Language header. Neither appears as an input to this collector's locale loop. Those interfaces can be relevant in a broader investigation, but their values are not recovered by expanding a comma-separated CreepJS locale line. The timezone, locale and language analysis separates those settings and observation points; it does not turn their different representations into one universal equality rule.

Missing samples and the renderer guard

Every formatting callback is wrapped in the shared caniuse helper. In the inspected src/errors/index.ts, a thrown callback returns undefined. The Intl calls use that callback form without a later property-chain traversal. An unavailable constructor, rejected option or exception during formatting can therefore converge on the same missing sample value. The helper does not attach the exception category to that returned value. An absent result alone cannot distinguish those possible causes.

The outer getIntl() function has its own try/catch. If an error escapes that outer scope, the module records an unsuccessful test, calls the error-capture helper and returns no module result. That differs from one sample callback failing while the rest of the returned object exists. Conversely, reaching the source's passed: true log line does not assert that every sample has a nonmissing value: callback errors may already have been converted to undefined inside the successful outer path.

Rendering introduces another layer. At this pinned revision, intlHTML(fp) tests !fp.htmlElementVersion before its normal Intl rendering path. That condition names the HTML-element report, not fp.intl. When the condition is true, the function returns the Intl card with blocked annotations. This is a property of the inspected renderer code, not a claim that a real browser failed Intl. An Intl-looking blocked card cannot, by its label alone, prove that a specific internationalization constructor was unavailable.

When the guard permits the normal rendering path, the renderer destructures fp.intl || {} and joins the locale and sample values with <br>. A missing individual value can occupy an empty position in that string assembly. The display order is locale, date, display name, number, relative time, list and plural category; it is not the property order of the returned object. Counting visible lines without checking the source order can misassign a phrase to the wrong formatter.

Source stateResult at that layerUnsupported explanation to avoid
A sample callback throwsThat sample becomes undefinedNaming a specific exception from the blank value
One no-argument constructor attempt throwsLocale accumulation skips that attemptDeclaring the whole constructor unsupported
The outer collector catches an errorNo module report is returnedTreating every sample as individually tested and failed
htmlElementVersion is absent or falseyRenderer selects its blocked-card branchAttributing the display guard directly to Intl capability
Normal rendering receives an absent sampleThe joined display can contain an empty positionSubstituting an invented localized phrase

These cases support a concrete triage sequence: locate the renderer branch, determine whether an Intl object exists, then identify the sample callback if only one value is missing. That order avoids diagnosing an API from a presentation fallback. It also preserves a useful distinction in support records: “field absent,” “module absent” and “blocked-card branch” refer to different evidence, even when an interface makes them look similar. No browser execution is claimed for these source-derived cases.

Inherited concerns and formatted text

The Intl collector initializes lied by reading seven lieProps keys ending in .resolvedOptions, one for each constructor named above. JavaScript || keeps the first truthy operand; the expression falls back to false when none is truthy. It is not a loop that formats six strings and compares them with stored reference phrases. The sample-producing code does not subsequently turn a changed month, compact-number expression or plural category into a local lied finding.

This matters when comparing a visible report badge or warning with the displayed text. Two reports could, as a hypothetical case, contain different formatter strings while both lack an inherited truthy concern. Another case could keep the same visible phrases but inherit a concern about a resolvedOptions method. Neither case is a measured result here. They illustrate why formatted data and an integrity assessment have to remain separate fields rather than being inferred from one another.

Producer coverage must be checked independently of consumer names. The inspected src/lies/index.ts explicitly registers Intl.DateTimeFormat with targets including format, formatRange, formatToParts and resolvedOptions. It also explicitly registers Intl.RelativeTimeFormat with resolvedOptions. Those two registrations do not make the consumer's seven-key list evidence of seven equivalent producer checks. This statement is bounded to the inspected registrations; it is not an audit of every possible mutation elsewhere in the project.

Source layerConcrete evidenceInterpretation boundary
Intl consumerSeven .resolvedOptions concern keys joined by ORNames that may influence lied, not a test count
DateTimeFormat registrationFour named targets including resolvedOptionsAn explicit search request in this revision
RelativeTimeFormat registrationresolvedOptions targetAnother explicit search request
Formatter callbacksFixed sample inputs and optionsFormatted values, without a local reference-string verdict
RendererTruthiness selects rejected stylingA presentation of recorded concern, not a probability

The renderer uses truthiness again for its rejected class and badge styling. A separate LowerEntropy.TIME_ZONE condition can affect styling when the inherited concern is not selected. A colored badge therefore needs the renderer condition behind it. It is not a documented confidence percentage or a diagnosis of which product setting should change. The source revision, concern key and report layer provide more information than the color alone.

A report-comparison decision matrix

The first comparison should identify what changed. A different date phrase, a different locale aggregate, a missing callback result and a truthy inherited concern are four different findings. A single screenshot can conceal those distinctions, especially when the constructor loop has already removed duplicates. Before attributing a difference to a browser setting, preserve the field name and the exact source revision that defines its inputs and transformations.

Difference being investigatedContext requiredBounded next action
Date phrase differsFixed timestamp, month/zone options, default locale and time zoneCompare formatter configuration before inferring a location
Compact-number wording differs21000000, compact notation, long display and locale dataCheck matching options and runtime revision
Locale aggregate has fewer distinct valuesConstructor success paths and deduplicationInspect per-constructor results rather than guessing an omitted API
Only display-name output is missingThe configured type: 'language' callDistinguish callback failure from the separate no-argument locale attempt
Visible samples match but concern styling differsActual inherited key and renderer conditionInspect the recorded concern, not the sample text
Entire card uses blocked annotationshtmlElementVersion guard and Intl object presenceIdentify the selected display branch first

For a date-format comparison, changing only the browser's time-zone configuration is different from changing the numeric timestamp. The source fixes the latter and leaves the former defaulted. The record should not call the resulting date phrase a captured clock value. If the source revision later supplies an explicit zone, that changes the comparison contract even if the UI continues to label the line simply as a date.

For list and number comparisons, preserve strings at the correct level. The list contains the strings 0 and 1; the number sample contains the numeric value 21000000. Replacing both with a shared “numeric formatting” field removes the distinction between list punctuation and number notation. Exact string differences may warrant inspecting locale data, but a normalized display chosen for an application is not evidence that the detector's original output matched.

For the locale aggregate, a shorter string is not automatically a regression. Deduplication can collapse several successful resolutions into one entry, while exceptions can remove attempted constructors from the accumulation. Those paths require different follow-up evidence. If per-constructor provenance was not retained, the final aggregate cannot reconstruct it. A guessed association between a locale and one of the seven constructor names would add information that the report no longer contains.

A minimal source-bound record

A support record can keep the comparison useful without exporting the full detector result or a stable identity digest. Proposed fields include sourceRevision, reportField, constructor, fixedInput, options, collectionState and displayBranch. If an inherited concern is the subject, retain its named key and the layer that supplied it. These are proposed diagnostic fields, not a claim that CreepJS returns an object with this schema.

The date sample's options should distinguish an omitted time zone from an explicitly selected one. The display sample should retain type: 'language' rather than just its constructor name. A locale-loop record should identify a skipped attempt instead of storing a fabricated locale value for it. Such distinctions are concrete inputs to the decision matrix; they do not require collecting unrelated request headers, page text or a person's geographic history.

BotBrowser's documentation describes --bot-timezone, --bot-locale and --bot-languages as separate controls, with automatic defaults and explicit overrides. The product documentation is the source for those configuration claims; CreepJS and MDN do not document BotBrowser behavior. A setting can define the intended browser configuration without proving identical internationalization data across versions, a real-world location, or acceptance by an outside service. No recommendation to change a setting follows merely from a warning color.

When an observed record lacks the relevant source field, the remaining conclusion should stay narrow. A missing constructor mapping prevents a per-constructor locale conclusion; a blank callback result prevents naming its exception; an inherited concern without its key prevents locating the affected method. The practical remedy is to obtain the smallest missing comparison input. Replacing these unknowns with a device label would make the report more definite while making its explanation less accurate.

FAQ: Intl report interpretation

Does the date line show when the detector ran?

The source supplies the fixed timestamp 963644400000. Collection timing is a different record. The long month and time-zone-name options format that historical input using the formatter context; a localized phrase does not turn the fixed number into a measurement of the current clock.

Why can a supported DisplayNames constructor be absent from locale collection?

The locale helper supplies no options, whereas the formatted display-name sample provides type: 'language'. MDN's constructor requirements explain why those calls can follow different paths. The helper catches a constructor exception and omits that attempt from its accumulation.

Does one locale entry mean only one constructor worked?

No. The Set removes repeated successful locale values before conversion to a string. Several constructors can contribute the same value. The aggregate does not preserve a successful-constructor count or a table assigning every constructor to its resolved locale.

Does lied mean the visible text failed a reference comparison?

The pinned collector consumes existing method concerns through seven named keys. Its sample callbacks produce values without a local expected-phrase comparison. Interpreting a concern requires its provenance; comparing the displayed text alone cannot recover the originating integrity finding.

Is a blocked Intl card proof that Intl is disabled?

The inspected rendering branch checks htmlElementVersion. A blocked annotation is therefore insufficient to identify an internationalization failure. The Intl object, individual callback states and selected renderer branch must be inspected separately before assigning an API-level explanation.

Can a locale result establish a visitor's physical country?

A resolved formatting locale describes the internationalization service's selection, not a location measurement. It should not be substituted for a person's preference, citizenship or current country. The detector's string contains neither a consented location fix nor the context needed for that inference.

Sources

Practical conclusion

An Intl report becomes interpretable when each value remains attached to its constructor, fixed input, options and failure path. Keep the deduplicated locale aggregate separate from six formatted samples; trace inherited concern keys and the actual renderer guard before interpreting missing or styled output. When a comparison lacks that context, obtain the missing field rather than assigning a device identity or changing a browser configuration on the basis of a label.

#Fingerprinting#Privacy#Locale

This article is part of the guide: What Is a Browser Fingerprint?

Take BotBrowser from research to production

The guides cover the model first, then move into cross-platform validation, isolated contexts, and scale-ready browser deployment.