1818= Configuring Encoding Detectors
1919
2020Tika uses a chain of _encoding detectors_ to determine the character encoding
21- of plain text and HTML content. `DefaultEncodingDetector` loads detectors via
22- the Java service-provider interface (SPI) and runs them in registration order;
23- the first non-null result wins.
21+ of plain text and HTML content. `DefaultEncodingDetector` discovers detectors
22+ via the Java service-provider interface (SPI, `META-INF/services`).
2423
25- The default chain is `html-encoding-detector`, `universal-encoding-detector`,
26- and `icu4j-encoding-detector`.
24+ The chain runs in one of two modes:
25+
26+ * *collect-all* — when a `MetaEncodingDetector` is present (the 4.x default
27+ includes one), every base detector runs and contributes candidate encodings,
28+ then the meta detector picks the best one by decode quality. Registration
29+ order does not matter.
30+ * *first-match-wins* — otherwise, detectors run in registration order and the
31+ first non-null result is used.
2732
2833== Default Detection Chain
2934
30- With the stock dependencies on the classpath (the modules
31- `tika-encoding-detector-html`, `tika-encoding-detector-universal`, and
32- `tika-encoding-detector-icu4j`):
35+ The stock 4.x distribution registers five detectors:
3336
3437[cols="1,2,3"]
3538|===
36- |Step |Detector |Returns non-null when…
39+ |Detector |Module |Role
40+
41+ |`bom-detector`
42+ |`tika-core`
43+ |Emits a candidate from a leading byte-order mark.
44+
45+ |`metadata-charset-detector`
46+ |`tika-core`
47+ |Emits a candidate from declarative hints (`Content-Type` charset,
48+ `Content-Encoding`) in the `Metadata` object.
3749
38- |1
3950|`html-encoding-detector`
40- |An HTML `<meta charset="…">` or `<meta http-equiv="Content-Type">` tag is
41- found. Fast lenient regex matcher with a curated subset of WHATWG label
42- aliases.
51+ |`tika-encoding-detector-html`
52+ |Emits a candidate from an HTML `<meta charset>` / `http-equiv` tag (lenient
53+ regex over a curated subset of WHATWG label aliases) .
4354
44- |2
45- |`universal-encoding-detector`
46- |A state-machine structural prober (juniversalchardet fork) recognises the
47- byte pattern as a known encoding (UTF-8, GB18030, Big5, EUC-JP, several
48- ISO-8859 variants, etc.).
55+ |`mojibuster-encoding-detector`
56+ |`tika-encoding-detector-mojibuster`
57+ |Byte-bigram Naive Bayes classifier plus structural detectors for UTF-32 and
58+ UTF-16 and a UTF-8 grammar gate.
4959
50- |3
51- |`icu4j-encoding-detector `
52- |ICU4J's `CharsetDetector` returns a match. Catches additional single-byte
53- encodings (Windows code pages, IBM/EBCDIC variants, etc.) .
60+ |`junk-filter-encoding-detector`
61+ |`tika-ml-junkdetect `
62+ |`MetaEncodingDetector` that picks among the other detectors' candidates by
63+ script-aware decode quality. Always runs last .
5464|===
5565
56- The chain is permissive — first-match-wins. A declared charset
57- (e.g. from a `<meta charset>` tag) wins over later structural or statistical
58- detectors.
66+ Because `junk-filter-encoding-detector` is a `MetaEncodingDetector`, the chain
67+ runs collect-all: detector order is irrelevant, and a declaration (a BOM or a
68+ `<meta charset>` tag) does *not* automatically win. The junk filter will
69+ override a declaration — or even a BOM — when the byte evidence strongly
70+ contradicts it.
71+
72+ NOTE: This is a behaviour change from 3.x, whose default chain was
73+ `html` / `universal` / `icu4j` with first-match-wins (a declaration always
74+ won). `universal-encoding-detector` and `icu4j-encoding-detector` are no longer
75+ in the default distribution; see <<restore-3x,Restore the 3.x chain>>.
5976
6077== Available Detectors
6178
@@ -66,49 +83,45 @@ referenced by their SPI name in JSON configuration.
6683|===
6784|Name |Module |Description
6885
69- |`html-encoding-detector`
70- |`tika-encoding-detector-html`
71- |Fast lenient regex matcher for `<meta charset>` / `http-equiv` tags, with a
72- curated subset of WHATWG label aliases. Auto-registered (in default chain).
73-
74- |`universal-encoding-detector`
75- |`tika-encoding-detector-universal`
76- |State-machine structural prober (juniversalchardet fork). Auto-registered
77- (in default chain).
86+ |`bom-detector`
87+ |`tika-core`
88+ |Reads a leading byte-order mark. In the default chain.
7889
79- |`icu4j-encoding-detector`
80- |`tika-encoding-detector-icu4j`
81- |Wraps ICU4J's `CharsetDetector`. Auto-registered (in default chain).
90+ |`metadata-charset-detector`
91+ |`tika-core`
92+ |Reads declarative hints (`Content-Type` charset, `Content-Encoding`) from the
93+ `Metadata` object. In the default chain.
8294
83- |`standard- html-encoding-detector`
95+ |`html-encoding-detector`
8496|`tika-encoding-detector-html`
85- |Spec-strict WHATWG prescan algorithm. Not in the default chain — opt in
86- explicitly if you need strict WHATWG tokenisation (e.g. ignoring charset
87- declarations inside HTML comments or other contexts the lenient regex may
88- match).
97+ |Fast lenient regex matcher for `<meta charset>` / `http-equiv` tags. In the
98+ default chain.
8999
90100|`mojibuster-encoding-detector`
91101|`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. Not in the default chain — opt in
94- explicitly.
102+ |Byte-bigram Naive Bayes classifier with structural UTF-32/UTF-16 detectors and
103+ a UTF-8 grammar gate. In the default chain.
95104
96105|`junk-filter-encoding-detector`
97106|`tika-ml-junkdetect`
98- |Text-quality arbitrator (`MetaEncodingDetector`) that picks among other
99- detectors' candidates by decode quality. Not in the default chain — opt in
100- explicitly.
107+ |Text-quality arbitrator (`MetaEncodingDetector`). In the default chain; runs
108+ last.
101109
102- |`bom-detector`
103- |`tika-core`
104- |Reads the first 4 bytes for BOM signatures. Helper component, used
105- internally by `AutoDetectReader`. Not normally added to the SPI chain.
110+ |`standard-html-encoding-detector`
111+ |`tika-encoding-detector-html`
112+ |Spec-strict WHATWG prescan algorithm. Not in the default chain — opt in if you
113+ need strict WHATWG tokenisation (e.g. ignoring charset declarations inside HTML
114+ comments).
106115
107- |`metadata-charset-detector`
108- |`tika-core`
109- |Reads declarative hints (`Content-Type` charset, `Content-Encoding`) from
110- the `Metadata` object. Helper component, used by parsers that consult
111- `Content-Type` directly. Not normally added to the SPI chain.
116+ |`universal-encoding-detector`
117+ |`tika-encoding-detector-universal`
118+ |State-machine structural prober (juniversalchardet fork). Not bundled and not
119+ auto-discovered; add the jar and configure it explicitly to use it.
120+
121+ |`icu4j-encoding-detector`
122+ |`tika-encoding-detector-icu4j`
123+ |Wraps ICU4J's `CharsetDetector`. Not bundled and not auto-discovered; add the
124+ jar and configure it explicitly to use it.
112125|===
113126
114127== Configuration Examples
@@ -124,83 +137,102 @@ auto-registered detectors:
124137 "encoding-detectors": [
125138 {
126139 "default-encoding-detector": {
127- "exclude": ["icu4j -encoding-detector"]
140+ "exclude": ["html -encoding-detector"]
128141 }
129142 }
130143 ]
131144}
132145----
133146
147+ NOTE: Do not combine `default-encoding-detector` with other explicit detector
148+ entries in the same list. When combined, the loader wraps everything in an
149+ outer composite that has no `MetaEncodingDetector` at its top level, so
150+ collect-all arbitration is silently lost and the explicit detectors are never
151+ reached. Use an explicit chain (see below) when you need to configure
152+ individual detectors.
153+
134154=== Specify the chain explicitly
135155
136- To replace the SPI-discovered chain with an explicit ordered list:
156+ To replace the SPI-discovered chain with an explicit ordered list. Include
157+ `junk-filter-encoding-detector` (last) to keep collect-all arbitration; omit it
158+ for first-match-wins:
137159
138160[source,json]
139161----
140162{
141163 "encoding-detectors": [
142164 {"html-encoding-detector": {}},
143- {"universal-encoding-detector": {}}
165+ {"mojibuster-encoding-detector": {}},
166+ {"junk-filter-encoding-detector": {}}
144167 ]
145168}
146169----
147170
148171=== Configure the HTML detector's read limit
149172
150- `html-encoding-detector` reads up to 65 536 bytes by default when scanning
151- for the `<meta charset>` tag. Raise it if your documents embed large
152- `<script>` blocks before the meta tag (TIKA-2485):
173+ `html-encoding-detector` reads up to 65 536 bytes by default when scanning for
174+ the `<meta charset>` tag. Raise it if your documents embed large `<script>`
175+ blocks before the meta tag (TIKA-2485). (`mojibuster-encoding-detector` reads a
176+ larger content probe, so in the default chain this limit matters mainly for very
177+ large preambles.)
178+
179+ To configure `markLimit`, specify the full chain explicitly. An explicit list
180+ that includes `junk-filter-encoding-detector` keeps collect-all arbitration; the
181+ configured `html-encoding-detector` participates as a base detector alongside
182+ Mojibuster, and the junk filter arbitrates as usual:
153183
154184[source,json]
155185----
156186{
157187 "encoding-detectors": [
158- {
159- "html-encoding-detector": {
160- "markLimit": 131072
161- }
162- },
163- {"universal-encoding-detector": {}},
164- {"icu4j-encoding-detector": {}}
188+ {"html-encoding-detector": {"markLimit": 131072}},
189+ {"mojibuster-encoding-detector": {}},
190+ {"junk-filter-encoding-detector": {}}
165191 ]
166192}
167193----
168194
169195=== Use the spec-strict WHATWG HTML detector
170196
171- If your input HTML has charset declarations inside comments (or other
172- contexts where the lenient regex would false-match), opt in to the
173- spec-strict prescan:
197+ If your input HTML has charset declarations inside comments (or other contexts
198+ where the lenient regex would false-match), opt in to the spec-strict prescan:
174199
175200[source,json]
176201----
177202{
178203 "encoding-detectors": [
179204 {"standard-html-encoding-detector": {}},
180- {"universal -encoding-detector": {}},
181- {"icu4j -encoding-detector": {}}
205+ {"mojibuster -encoding-detector": {}},
206+ {"junk-filter -encoding-detector": {}}
182207 ]
183208}
184209----
185210
186- === Add the Mojibuster + JunkFilter chain (opt-in)
211+ [#restore-3x]
212+ === Restore the 3.x detection chain (universal + icu4j)
187213
188- The byte-bigram NB classifier (`mojibuster-encoding-detector`) and the
189- text-quality arbitrator (`junk-filter-encoding-detector`) are available as
190- opt-in components. They require the `tika-encoding-detector-mojibuster`
191- and `tika-ml-junkdetect` modules on the classpath:
214+ The 4.x default no longer bundles or auto-registers
215+ `universal-encoding-detector` and `icu4j-encoding-detector`. To get the legacy
216+ 3.x behaviour (`html` / `universal` / `icu4j`, first-match-wins) you must do
217+ *both*:
218+
219+ . *Add the jars to the classpath.* They are no longer in the `tika-app` /
220+ `tika-server-standard` packages, so supply `tika-encoding-detector-universal`
221+ and `tika-encoding-detector-icu4j` yourself (for example via `-Dtika.extras.dir`
222+ — see xref:configuration/index.adoc[the configuration overview]).
223+ . *Configure the chain explicitly.* An explicit chain with no
224+ `MetaEncodingDetector` runs first-match-wins:
192225
193226[source,json]
194227----
195228{
196229 "encoding-detectors": [
197230 {"html-encoding-detector": {}},
198- {"mojibuster -encoding-detector": {}},
199- {"junk-filter -encoding-detector": {}}
231+ {"universal -encoding-detector": {}},
232+ {"icu4j -encoding-detector": {}}
200233 ]
201234}
202235----
203236
204- `junk-filter-encoding-detector` is a `MetaEncodingDetector` — it collects
205- candidates from the other detectors and picks the cleanest decoding via a
206- script-aware text-quality model. It must run last.
237+ Dropping the jars on the classpath alone is *not* enough: unlike the other
238+ detectors, these two are config-only and are not auto-discovered via SPI.
0 commit comments