1818= Configuring Encoding Detectors
1919
2020Tika uses a chain of _encoding detectors_ to determine the character encoding
21- of plain text and HTML content. The chain is controlled by
22- `DefaultEncodingDetector`, which loads detectors via the Java service-provider
23- interface (SPI) and runs them in registration order.
21+ of plain text and HTML content. `DefaultEncodingDetector` loads detectors
22+ via the Java service-provider interface (SPI) and runs them in registration
23+ order. See xref:../advanced/charset-detection-design.adoc[Charset Detection Pipeline]
24+ for design details.
2425
2526== Default Detection Chain
2627
27- The default chain when `tika-charset-detectors-core` is on the classpath:
28+ With the stock dependencies on the classpath:
2829
29- [cols="1,2,1 "]
30+ [cols="1,2,2 "]
3031|===
3132|Step |Detector |Returns non-null when…
3233
3334|1
34- |`http-header-encoding -detector`
35- |A `charset=` parameter is present in the `Content-Type` metadata field
36- (e.g. populated from an HTTP response header) .
35+ |`bom -detector`
36+ |A UTF-8, UTF-16 LE/BE, or UTF-32 LE/BE byte-order mark is present.
37+ Emits DECLARATIVE .
3738
3839|2
39- |`bom-encoding-detector`
40- |A UTF-8, UTF-16 LE/BE, or UTF-32 LE/BE byte-order mark is present.
40+ |`metadata-charset-detector`
41+ |A `charset=` parameter is present in the `Content-Type` metadata field
42+ (populated from an HTTP response header or similar). Emits DECLARATIVE.
4143
4244|3
43- |`html-encoding-detector`
44- |An HTML `<meta charset="…">` or `Content-Type` http-equiv tag is found
45- (fast lenient regex matcher, curated WHATWG label aliases).
45+ |`naive-bayes-pipeline-encoding-detector`
46+ |A structural UTF-32 check, structural UTF-16 specialist, UTF-8 grammar
47+ gate, and 33-class byte-bigram Naive Bayes classifier. STRUCTURAL for
48+ structural hits; STATISTICAL for NB predictions.
4649
4750|4
48- |`ml-encoding-detector`
49- |The built-in statistical model classifies the byte stream (~46 encodings,
50- ~185 KB model bundled as a resource).
51-
52- |5 _(if present)_
53- |`universal-encoding-detector`
54- |State-machine structural prober (juniversalchardet fork). Automatically
55- joins the chain when `tika-charset-detectors-universal` is on the classpath.
56- Complements ML: excels at short or repetitive CJK byte sequences (ZIP entry
57- names, single-word filenames) where statistical models lack sufficient texture.
51+ |`html-encoding-detector`
52+ |An HTML `<meta charset="…">` or `<meta http-equiv="Content-Type">` tag
53+ is found (fast lenient regex matcher, curated WHATWG label aliases).
54+ Emits DECLARATIVE.
5855
59- |6 _(if present)_
56+ |5
6057|`charsoup-encoding-detector`
61- |A `MetaEncodingDetector` that runs after all base detectors. When they all
62- agree it returns the unanimous result; when they disagree it uses language-
63- detection scoring — with a junk-ratio fallback (fewest undefined codepoints
64- wins) for content too short for reliable language detection.
58+ |`MetaEncodingDetector` — arbitrates across all base-detector candidates
59+ using a character-bigram language model. When one or more base detectors
60+ return a result, CharSoup decodes the probe with each candidate charset
61+ and picks the one whose decoded text scores best for any supported
62+ language. Always runs last.
6563|===
6664
67- NOTE: `universal-encoding-detector` and `charsoup-encoding-detector` are
68- supplied by separate optional modules (`tika-charset-detectors-universal` and
69- `tika-langdetect-charsoup` respectively). Each is loaded automatically via
70- SPI when its module is on the classpath and requires no extra configuration.
71-
72- == Design Rationale
73-
74- The chain combines two complementary detection strategies:
75-
76- * **Statistical (ML)** — learns byte-bigram distributions from training data.
77- Works well for documents with enough varied content (~100+ bytes).
78- * **Structural (Universal)** — applies encoding-spec constraints (is this a
79- valid lead+trail byte pair for Shift_JIS / EUC-JP / Big5 / GBK?). Works
80- on as few as two bytes and is unaffected by content length.
81-
82- Rules beat statistics at the extremes (very short or highly structured input);
83- statistics beat rules in the ambiguous middle where distributions are rich.
84- `charsoup-encoding-detector` arbitrates when they disagree.
65+ NOTE: `charsoup-encoding-detector` is supplied by
66+ `tika-encoding-detector-charsoup` and loads automatically via SPI when
67+ the module jar is present. Omit it to get strict first-match-wins
68+ behaviour that honours declarations authoritatively — see
69+ <<opting-out-of-charsoup>>.
8570
8671== Available Detectors
8772
8873All detectors implement `org.apache.tika.detect.EncodingDetector` and can be
89- referenced by name in JSON configuration.
74+ referenced by their SPI name in JSON configuration.
9075
9176[cols="2,2,3"]
9277|===
9378|Name |Module |Description
9479
95- |`http-header-encoding-detector`
96- |`tika-charset-detectors-core`
97- |Reads `charset=` from the `Content-Type` metadata field. In the default chain.
80+ |`bom-detector`
81+ |`tika-core`
82+ |Reads the first 4 bytes for BOM signatures. In the default chain.
83+
84+ |`metadata-charset-detector`
85+ |`tika-core`
86+ |Reads declarative hints (`Content-Type` charset, `Content-Encoding`) from
87+ the `Metadata` object. Applies WHATWG label normalization
88+ (ISO-8859-1 and US-ASCII → windows-1252). In the default chain.
9889
99- |`bom-encoding-detector`
100- |`tika-charset-detectors-core`
101- |Byte-order mark detection (UTF-8/16/32). In the default chain.
90+ |`naive-bayes-pipeline-encoding-detector`
91+ |`tika-encoding-detector-mojibuster`
92+ |Byte-bigram Naive Bayes classifier plus structural detectors for UTF-32
93+ and UTF-16 and a UTF-8 grammar gate. 33 classes including CJK
94+ multi-byte, EBCDIC variants, DOS code pages, Cyrillic, Windows single-byte,
95+ ISO-8859-3/16, Mac, and UTF-8. In the default chain. See
96+ xref:../advanced/charset-detection-design.adoc[the design doc].
10297
10398|`html-encoding-detector`
104- |`tika-charset-detectors-core `
99+ |`tika-encoding-detector-html `
105100|Fast lenient regex matcher for `<meta charset>` / `http-equiv` tags, with a
106101curated subset of WHATWG label aliases. In the default chain.
107102
108- |`ml-encoding-detector`
109- |`tika-charset-detectors-core`
110- |Statistical multinomial logistic regression model (~46 encodings).
111- In the default chain.
112-
113- |`universal-encoding-detector`
114- |`tika-charset-detectors-universal`
115- |State-machine structural prober; wraps the `com.github.albfernandez:juniversalchardet`
116- fork. Auto-registers when the module jar is on the classpath.
117-
118103|`standard-html-encoding-detector`
119- |`tika-charset-detectors-core `
104+ |`tika-encoding-detector-html `
120105|Spec-strict WHATWG prescan algorithm. Not in the default chain — opt in
121106explicitly if you need strict WHATWG tokenisation (e.g. ignoring charset
122107declarations inside comments or other contexts the lenient regex may match).
123108
109+ |`charsoup-encoding-detector`
110+ |`tika-encoding-detector-charsoup`
111+ |Language-aware arbitrator (`MetaEncodingDetector`). In the default
112+ chain when the module jar is on the classpath; always runs last.
113+
114+ |`mojibuster-encoding-detector`
115+ |`tika-encoding-detector-mojibuster`
116+ |Legacy maxent charset classifier. Still available for explicit opt-in;
117+ not auto-registered.
118+
124119|`icu4j-encoding-detector`
125- |`tika-charset-detectors-icu4j`
126- |Wraps ICU4J `CharsetDetector`. _Legacy_ — the ML + Universal chain
127- supersedes it for most use cases. Available for explicit opt-in when
128- `com.ibm.icu:icu4j` is already on the classpath.
120+ |`tika-encoding-detector-icu4j`
121+ |Wraps ICU4J `CharsetDetector`. Legacy — the NB pipeline supersedes it
122+ for most cases. Not auto-registered.
129123
130- |`charsoup -encoding-detector`
131- |`tika-langdetect-charsoup `
132- |Language-aware arbitrator (`MetaEncodingDetector` ). Auto-registers when
133- the module jar is on the classpath; always runs last .
124+ |`universal -encoding-detector`
125+ |`tika-encoding-detector-universal `
126+ |State-machine structural prober (juniversalchardet fork ). Not
127+ auto-registered; opt in if you specifically need it .
134128|===
135129
136130== Configuration Examples
@@ -143,63 +137,76 @@ the module jar is on the classpath; always runs last.
143137 "encoding-detectors": [
144138 {
145139 "default-encoding-detector": {
146- "exclude": ["bom-encoding- detector"]
140+ "exclude": ["bom-detector"]
147141 }
148142 }
149143 ]
150144}
151145----
152146
153- === Restrict to a lightweight chain (no Universal, no CharSoup)
147+ [[opting-out-of-charsoup]]
148+ === Strict declared-charset honoring (no CharSoup arbitration)
154149
155- Useful in resource-constrained environments when you only need the core
156- statistical chain:
150+ By default, CharSoup arbitrates across all candidates including DECLARATIVE
151+ ones — which means a `<meta charset>` tag is not automatically
152+ authoritative. If you want declarations to win unconditionally (HTML5-spec
153+ behaviour), omit CharSoup:
157154
158155[source,json]
159156----
160157{
161158 "encoding-detectors": [
162- {"http-header-encoding -detector": {}},
163- {"bom-encoding -detector": {}},
159+ {"bom -detector": {}},
160+ {"metadata-charset -detector": {}},
164161 {"html-encoding-detector": {}},
165- {"ml -encoding-detector": {}}
162+ {"naive-bayes-pipeline -encoding-detector": {}}
166163 ]
167164}
168165----
169166
167+ Without CharSoup, `CompositeEncodingDetector` runs in first-match-wins
168+ mode. Trade-off: lying declarations (common on the legacy web)
169+ propagate unfiltered. See
170+ xref:../advanced/charset-detection-design.adoc#opting-out-of-arbitration[the design doc]
171+ for details.
172+
170173=== Configure the HTML detector's read limit
171174
172- The default limit is 8 192 bytes. Raise it if your HTML documents embed
173- large `<script>` blocks before the `<meta charset>` declaration.
175+ `html-encoding-detector` reads up to 65 536 bytes by default when
176+ scanning for the `<meta charset>` tag. Raise it if your documents embed
177+ large `<script>` blocks before the meta tag (TIKA-2485):
174178
175179[source,json]
176180----
177181{
178182 "encoding-detectors": [
179- {"http-header-encoding -detector": {}},
180- {"bom-encoding -detector": {}},
183+ {"bom -detector": {}},
184+ {"metadata-charset -detector": {}},
181185 {
182186 "html-encoding-detector": {
183- "markLimit": 65536
187+ "markLimit": 131072
184188 }
185189 },
186- {"ml-encoding-detector": {}}
190+ {"naive-bayes-pipeline-encoding-detector": {}},
191+ {"charsoup-encoding-detector": {}}
187192 ]
188193}
189194----
190195
191- === Recreate the pre-4.x default (HTML + juniversalchardet + ICU4J )
196+ === Legacy chain (ICU4J + juniversalchardet)
192197
193- Not recommended — the new chain is strictly better — but possible for
194- regression testing or comparison:
198+ Not recommended — the NB pipeline is strictly better on accuracy and
199+ latency — but available for regression testing or comparison:
195200
196201[source,json]
197202----
198203{
199204 "encoding-detectors": [
205+ {"bom-detector": {}},
206+ {"metadata-charset-detector": {}},
200207 {"html-encoding-detector": {}},
201- {"universal -encoding-detector": {}},
202- {"icu4j -encoding-detector": {}}
208+ {"icu4j -encoding-detector": {}},
209+ {"universal -encoding-detector": {}}
203210 ]
204211}
205212----
0 commit comments