IsCHTMLBrowser
Tests a user agent string for a compact HTML feature-phone browser. Runtime-proven on a live Marketing Cloud Engagement CloudPage — including the true path, which two feature-phone agent families still produce, while the empty string aborts the page.
Syntax
IsCHTMLBrowser(userAgent) → boolean
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
userAgent |
string | Yes | User agent string to test, typically the request’s own user-agent header |
Example
%%[ VAR @chtml SET @chtml = IsCHTMLBrowser("DoCoMo/2.0 N905i(c100;TB;W24H16)") ]%%
%%=v(@chtml)=%%
Renders True.
Testing the actual visitor means reading the request header into a variable first, then passing that variable:
%%[
VAR @ua, @chtml
SET @ua = HTTPRequestHeader("user-agent")
SET @chtml = IsCHTMLBrowser(@ua)
]%%
%%=IIf(@chtml, "compact markup", "full markup")=%%
Reading the header inline as the argument aborts the page, and so does an empty value — see below.
Return value
boolean — True when the string is a compact HTML browser agent, False otherwise.
Both literals were produced in the same render, as the capitalised words True and False. They are genuine booleans: each compares equal to the corresponding boolean value.
Behaviour
It really inspects the string, on an ordinary page request. In a single response two feature-phone agents returned True and three other strings returned False, so this is not a function that answers the same way regardless of input.
Two unrelated agent families are recognised. A DoCoMo i-mode agent and a KDDI handset agent both return True despite having nothing textually in common, so the check knows agent families rather than one hard-coded string.
The word does not trigger it. IsCHTMLBrowser("chtml") returns False, while agents that never contain that word return True.
The request’s own user agent decides the live result. The same deployed page, fetched twice without redeploying, returned False with a desktop User-Agent header and True with a feature-phone one.
A number is harmless. IsCHTMLBrowser(0) returns False.
The empty string aborts the page
Passing an empty value is the one input in this family that is not survivable: the request fails with HTTP 422 and everything the page had already rendered is discarded. The sibling checks IsEmailAddress, IsPhoneNumber and Domain all answer normally for the same input, so this is specific to this function. Two shapes reach it in practice — a literal empty string, and a request that sends no user-agent header at all, which leaves HTTPRequestHeader("user-agent") empty. Guard the value before calling:
%%[
VAR @ua, @chtml
SET @ua = HTTPRequestHeader("user-agent")
SET @chtml = false
IF NOT Empty(@ua) THEN
SET @chtml = IsCHTMLBrowser(@ua)
ENDIF
]%%
Show test script
%%[
VAR @b, @ua
SET @b = RequestParameter("b")
/* the header must be read into a variable here; passing the header call
inline as the argument below aborts the branch */
SET @ua = HTTPRequestHeader("user-agent")
/* known-good control: renders on every request, so a run of HTTP 422s
can be told apart from a broken deploy */
OutputLine(Concat("CTRL=[", Uppercase("ok"), "]"))
/* constructed agents - safe on every request, and the only way to see
the true result without a feature phone to hand */
OutputLine(Concat("--- C start ---"))
OutputLine(Concat("C1_desktop=[", IsCHTMLBrowser("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"), "]"))
OutputLine(Concat("C2_imode=[", IsCHTMLBrowser("DoCoMo/2.0 N905i(c100;TB;W24H16)"), "]"))
OutputLine(Concat("C3_kddi=[", IsCHTMLBrowser("KDDI-CA31 UP.Browser/6.2.0.7.3.129 (GUI) MMP/2.0"), "]"))
OutputLine(Concat("C4_chtml_word=[", IsCHTMLBrowser("chtml"), "]"))
OutputLine(Concat("C5_junk=[", IsCHTMLBrowser("zzz-not-a-user-agent"), "]"))
OutputLine(Concat("--- C done ---"))
/* the real request header - fetch this branch twice with two different
User-Agent headers to see the answer change */
IF @b == "live" THEN
OutputLine(Concat("--- live start ---"))
OutputLine(Concat("UA3=[", @ua, "]"))
OutputLine(Concat("C_LIVE=[", IsCHTMLBrowser(@ua), "]"))
OutputLine(Concat("--- live done ---"))
ENDIF
/* a non-string argument */
IF @b == "g_num" THEN
OutputLine(Concat("--- g_num start ---"))
OutputLine(Concat("C_NUM=[", IsCHTMLBrowser(0), "]"))
OutputLine(Concat("--- g_num done ---"))
ENDIF
/* the rendered literals compared against real booleans */
IF @b == "g_tok" THEN
OutputLine(Concat("--- g_tok start ---"))
OutputLine(Concat("C_EQTRUE=[", IIf(IsCHTMLBrowser("DoCoMo/2.0 N905i(c100;TB;W24H16)") == true, "matches-true", "no"), "]"))
OutputLine(Concat("C_EQFALSE=[", IIf(IsCHTMLBrowser("Mozilla/5.0") == false, "matches-false", "no"), "]"))
OutputLine(Concat("--- g_tok done ---"))
ENDIF
]%%
Every marker and label in the test script goes through Concat(...), including single-argument ones. A bare string literal passed to OutputLine renders an empty line while the page still returns HTTP 200, so the marker silently vanishes.
The ?b=live branch only demonstrates anything if you request it twice with two different User-Agent headers. Requesting it with no User-Agent header at all aborts that branch, which is the empty-value case rather than a fault in the script.
Availability
| Platform | Available |
|---|---|
| Marketing Cloud Engagement | Yes |
| Marketing Cloud Next | No |
See also
- Empty — how to guard the user agent value before calling
- IsEmailAddress — a sibling Utility predicate that tolerates the empty string
- Official reference · ampscript.guide