HTTPGet
→ stringSends an HTTP GET request to the specified URL and returns the response body as a string.
Syntax
Platform.Function.HTTPGet(url, continueOnError, emptyContentHandling, headerNames, headerValues, statusVariable)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | URL to request |
continueOnError |
boolean | 6-arg form only | When true, the request terminates if an error occurs. When false, the request continues on error. Part of the all-or-nothing trailing group. |
emptyContentHandling |
string | number | 6-arg form only | How to handle a URL that returns empty content: 0 = allow empty, 1 = return error, 2 = skip subscriber. Part of the all-or-nothing trailing group. |
headerNames |
string[] | 6-arg form only | Array of header names to include in the GET request (pass null when none). Part of the all-or-nothing trailing group. |
headerValues |
string[] | 6-arg form only | Array of header values corresponding to headerNames (pass null when none). Part of the all-or-nothing trailing group. |
statusVariable |
number[] | 6-arg form only | Array intended to receive the HTTP status code, but observed empty at runtime even on success — do not rely on it. Part of the all-or-nothing trailing group. |
Only two call forms are valid: a single-argument call HTTPGet(url), or the full 6-argument call. The trailing five arguments (continueOnError through statusVariable) are an all-or-nothing group — supply all five together or none.
The argument count is a discontinuous overload, not a simple range. Only HTTPGet(url) or the full 6-argument form is valid, contradicting the docs that list the trailing arguments as independently optional.
Show test script — only 1 and 6 arguments are valid
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Differs-from-docs claim: the argument count of HTTPGet is a DISCONTINUOUS
* overload, not a simple range.
*
* Official docs: arguments 3-6 are independently optional, which would make
* every argument count from 1 to 6 valid.
* Older claim: all six arguments are required, which would make the
* 1-argument form invalid.
* SFMC runtime: ONLY a 1-argument call and the full 6-argument call work.
* 2, 3, 4 and 5 arguments all throw
* "Unable to retrieve security descriptor for this frame."
*
* Proves both halves of the claim:
* 1. Both valid arities really succeed — 1 argument and 6 arguments.
* 2. Every intermediate arity (2, 3, 4, 5) really throws, so the trailing
* five arguments are an all-or-nothing group.
* 3. TYPE-ACCEPTANCE (Number↔string): `emptyContentHandling` accepts the
* documented number (0) AND the numeric string ("0") in the valid
* 6-argument form (co-required trailing args kept valid), with the
* SAME response body — widens the Parameters type to string | number.
*
* SCOPE: evidence gathered on a CloudPage GET only.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
var URL = "https://ssjs.guide/robots.txt";
/* 1. The two valid arities. */
var one = Platform.Function.HTTPGet(URL);
assert("arity 1 succeeds and returns a string", String(typeof one), "string");
assert("arity 1 returns a non-empty body", one.length > 0 ? "true" : "false", "true");
var st = [];
var six = Platform.Function.HTTPGet(URL, false, 0, null, null, st);
assert("arity 6 succeeds and returns a string", String(typeof six), "string");
assert("arity 6 returns a non-empty body", six.length > 0 ? "true" : "false", "true");
assert("emptyContentHandling number 0 accepted (documented type)", six.length > 0 ? "true" : "false", "true");
/* 3. TYPE-ACCEPTANCE — emptyContentHandling numeric-string counterpart.
Keep co-required trailing args valid so the call stays in the 6-arg form. */
var stStr = [];
var sixStr = Platform.Function.HTTPGet(URL, false, "0", null, null, stStr);
assert("emptyContentHandling string \"0\" accepted (counterpart)", sixStr.length > 0 ? "true" : "false", "true");
assert("TYPE-ACCEPT number 0 and string \"0\" return the same body", sixStr === six ? "true" : "false", "true");
/* 2. Every intermediate arity throws — the trailing five are all-or-nothing. */
assertThrows("DEV arity 2 throws (docs imply it is valid)", function () {
return Platform.Function.HTTPGet(URL, false);
});
assertThrows("DEV arity 3 throws (docs imply it is valid)", function () {
return Platform.Function.HTTPGet(URL, false, 0);
});
assertThrows("DEV arity 4 throws (docs imply it is valid)", function () {
return Platform.Function.HTTPGet(URL, false, 0, null);
});
assertThrows("DEV arity 5 throws (docs imply it is valid)", function () {
return Platform.Function.HTTPGet(URL, false, 0, null, null);
});
assertThrows("DEV arity 0 throws (url is required)", function () {
return Platform.Function.HTTPGet();
});
</script>
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Parameters — the two valid call forms and the all-or-nothing
* trailing argument group.
*
* Proves:
* 1. The single-argument form HTTPGet(url) succeeds and returns the
* response body as a string (min_args is 1).
* 2. The full 6-argument form succeeds and also returns the body string
* (max_args is 6).
* 3. `url` is required: a 0-argument call throws.
* 4. DEVIATION marked "DEV": the argument count is a DISCONTINUOUS
* overload, not a simple range. Passing 2, 3, 4 or 5 arguments throws
* "Unable to retrieve security descriptor for this frame." The official
* docs list arguments 3-6 as INDEPENDENTLY OPTIONAL, which would make
* every count from 1 to 6 valid; an older claim said all six arguments
* are REQUIRED, which would make the 1-argument form invalid. Both are
* wrong — only 1 and 6 work.
* 5. `continueOnError` accepts both true and false, and
* `emptyContentHandling` accepts each documented value (0 allow empty,
* 1 return error, 2 skip subscriber), in the 6-argument form.
* 6. `headerNames` / `headerValues` accept null (no headers) as documented.
* 7. DEVIATION marked "DEV": `statusVariable` is documented as receiving
* the HTTP status code as statusVariable[0], but it is observed EMPTY
* even on a successful call (length 0, [0] undefined).
*
* SCOPE: evidence gathered on a CloudPage GET only; no email / automation /
* triggered-send send-context behaviour is exercised here.
*
* NOT ASSERTED: the actual effect of `continueOnError` and
* `emptyContentHandling` on error / empty-content responses. Both change
* SEND-CONTEXT behaviour (terminating a send, skipping a subscriber), which
* is not observable from a CloudPage request — only that the values are
* accepted is asserted here.
*
* EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
* longer matches the documented claim and the page must be revised.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
/* A small, stable, public endpoint: 40 bytes of text. */
var URL = "https://ssjs.guide/robots.txt";
/* 1. The single-argument form works and returns a string body. */
var body = Platform.Function.HTTPGet(URL);
assert("HTTPGet(url) returns a string", String(typeof body), "string");
assert("the returned body is non-empty", body.length > 0 ? "true" : "false", "true");
/* 2. The full 6-argument form works, with null header arrays. */
var status = [];
var content = Platform.Function.HTTPGet(URL, false, 0, null, null, status);
assert("the 6-argument form returns a string", String(typeof content), "string");
assert("the 6-argument body is non-empty", content.length > 0 ? "true" : "false", "true");
assert("both valid forms return the same body", content === body ? "true" : "false", "true");
/* 6. null is accepted for headerNames / headerValues (asserted above by the
successful call that passed null for both). */
assert("headerNames=null and headerValues=null are accepted", content.length > 0 ? "true" : "false", "true");
/* 7. DEVIATION — statusVariable stays empty even on success. */
assert("DEV statusVariable.length is 0 (docs: receives the status code)", String(status.length), "0");
assert("DEV statusVariable[0] is undefined (docs: the numeric HTTP status)", String(typeof status[0]), "undefined");
/* 3. url is required. */
assertThrows("HTTPGet() with 0 arguments throws (min_args is 1)", function () {
return Platform.Function.HTTPGet();
});
/* 4. DEVIATION — 2 to 5 arguments are all invalid. */
assertThrows("DEV 2 arguments throw (docs: args 3-6 independently optional)", function () {
return Platform.Function.HTTPGet(URL, false);
});
assertThrows("DEV 3 arguments throw (docs: args 3-6 independently optional)", function () {
return Platform.Function.HTTPGet(URL, false, 0);
});
assertThrows("DEV 4 arguments throw (docs: args 3-6 independently optional)", function () {
return Platform.Function.HTTPGet(URL, false, 0, null);
});
assertThrows("DEV 5 arguments throw (docs: args 3-6 independently optional)", function () {
return Platform.Function.HTTPGet(URL, false, 0, null, null);
});
/* 5. continueOnError and emptyContentHandling accept every documented value. */
var sA = [];
var cA = Platform.Function.HTTPGet(URL, true, 1, null, null, sA);
assert("continueOnError=true with emptyContentHandling=1 is accepted", cA.length > 0 ? "true" : "false", "true");
var sB = [];
var cB = Platform.Function.HTTPGet(URL, false, 2, null, null, sB);
assert("emptyContentHandling=2 (skip subscriber) is accepted", cB.length > 0 ? "true" : "false", "true");
assert("DEV statusVariable still empty on the emptyContentHandling=2 call", String(sB.length), "0");
</script>
Examples
// Valid form 1 - single argument, returns the response body as a string
var body = Platform.Function.HTTPGet("https://api.example.com/data");
var obj = Platform.Function.ParseJSON(body);
// Valid form 2 - full 6-argument form (the trailing five are all-or-nothing)
var status = [];
var content = Platform.Function.HTTPGet(
"https://api.example.com/data",
false,
0,
null,
null,
status
);
// status[0] is unreliable (observed empty even on success) - read the body from `content`
var parsed = Platform.Function.ParseJSON(content);
// 6-argument form with custom headers
var status2 = [];
var content2 = Platform.Function.HTTPGet(
"https://api.example.com/secure",
false,
0,
["x-request-id"],
["sampleValue"],
status2
);
For full transport control, use HTTP.Get (Core) or Script.Util.HttpRequest.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Examples — the three documented call shapes.
*
* Proves:
* 1. Valid form 1: var body = Platform.Function.HTTPGet(url) returns a
* string, and Platform.Function.ParseJSON(body) parses it into an
* object when the endpoint serves JSON.
* 2. Valid form 2: the full 6-argument form with null header arrays
* returns the body in `content`, while `status[0]` stays undefined —
* the example comment says to read the body from `content` and not to
* trust status[0], and that is exactly what happens.
* 3. The 6-argument form with CUSTOM HEADERS (parallel headerNames /
* headerValues arrays) is accepted and returns the body.
* 4. The See-Also note that HTTP.Get (Core) is the alternative transport:
* it returns an OBJECT with a Content field, not a bare string — which
* is why HTTPGet's string return value is worth documenting.
*
* SCOPE: evidence gathered on a CloudPage GET only. The example URLs
* api.example.com are placeholders and are NOT contacted; a small, stable,
* public endpoint is used instead.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
var TEXT_URL = "https://ssjs.guide/robots.txt";
var JSON_URL = "https://ssjs.guide/site-index.json";
/* 1. Valid form 1 — single argument, body string, then ParseJSON. */
var body = Platform.Function.HTTPGet(JSON_URL);
assert("form 1: typeof body is string", String(typeof body), "string");
assert("form 1: the body is non-empty", body.length > 0 ? "true" : "false", "true");
var obj = Platform.Function.ParseJSON(body);
assert("form 1: ParseJSON(body) yields an object", String(typeof obj), "object");
assert("form 1: the parsed value carries data", obj.length > 0 ? "true" : "false", "true");
/* 2. Valid form 2 — full 6-argument form, status[0] unreliable. */
var status = [];
var content = Platform.Function.HTTPGet(TEXT_URL, false, 0, null, null, status);
assert("form 2: typeof content is string", String(typeof content), "string");
assert("form 2: content is non-empty", content.length > 0 ? "true" : "false", "true");
assert("form 2: status[0] is undefined as the comment warns", String(typeof status[0]), "undefined");
assert("form 2: status.length is 0 as the comment warns", String(status.length), "0");
/* 3. 6-argument form with custom headers. */
var status2 = [];
var content2 = Platform.Function.HTTPGet(TEXT_URL, false, 0, ["x-request-id"], ["sampleValue"], status2);
assert("form 3: typeof content2 is string", String(typeof content2), "string");
assert("form 3: content2 is non-empty", content2.length > 0 ? "true" : "false", "true");
assert("form 3: the header form returns the same body as the null form", content2 === content ? "true" : "false", "true");
assert("form 3: status2 is empty too", String(status2.length), "0");
/* 4. The note: HTTP.Get (Core) is the object-returning alternative. */
var r = HTTP.Get(TEXT_URL);
assert("note: HTTP.Get returns an object, not a string", String(typeof r), "object");
assert("note: HTTP.Get exposes the body under .Content", String(r.Content) === content ? "true" : "false", "true");
</script>
Return Value
Returns the response body as a string. In the 6-argument form the statusVariable array is intended to receive the HTTP status code as statusVariable[0], but at runtime it was observed empty (statusVariable.length === 0, statusVariable[0] === undefined) even on a successful call — so do not depend on it.
The official Salesforce docs describe the return value as a numeric status, but the runtime returns the response body as a string. The statusVariable[0] out-parameter that was meant to carry the numeric status was observed empty at runtime even on success, so it is unreliable in a CloudPage context.
Show test script — returns the body string, not a numeric status
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Differs-from-docs claim: HTTPGet returns the RESPONSE BODY as a string.
*
* Official docs: the return value is a NUMERIC STATUS, and the numeric
* status is delivered via the statusVariable out-parameter as
* statusVariable[0].
* SFMC runtime: the return value is the response body as a string, and
* statusVariable is observed EMPTY even on a successful call.
*
* Proves both halves of the claim:
* 1. The return value is a string carrying the body, not a number and not
* a stringified status code.
* 2. The statusVariable out-parameter is empty after a successful call, so
* the numeric status is not delivered anywhere.
* 3. The recommended workaround — read the body from the return value, and
* use HTTP.Get / Script.Util.HttpRequest when you need the status code
* — actually works: HTTP.Get exposes a numeric Status field alongside
* the same body.
*
* SCOPE: evidence gathered on a CloudPage GET only.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
var URL = "https://ssjs.guide/robots.txt";
/* 1. The return value is the body string, not a numeric status. */
var status = [];
var value = Platform.Function.HTTPGet(URL, false, 0, null, null, status);
assert("DEV typeof the return value is string (docs: number)", String(typeof value), "string");
assert("DEV the return value is not the number 200 (docs: a status)", value === 200 ? "true" : "false", "false");
assert("DEV the return value is not the string '200' either", value === "200" ? "true" : "false", "false");
assert("the return value carries the response body", value.length > 0 ? "true" : "false", "true");
/* 2. The status out-parameter is empty on success. */
assert("DEV statusVariable.length is 0 after a SUCCESSFUL call", String(status.length), "0");
assert("DEV statusVariable[0] is undefined after a SUCCESSFUL call", String(typeof status[0]), "undefined");
/* 3. Workaround — HTTP.Get gives you a numeric status and the same body. */
var r = HTTP.Get(URL);
assert("workaround: HTTP.Get returns an object", String(typeof r), "object");
assert("workaround: HTTP.Get exposes a numeric Status field", String(typeof r.Status), "number");
assert("workaround: HTTP.Get .Content matches the HTTPGet return value", String(r.Content) === value ? "true" : "false", "true");
</script>
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Return Value — returns the response body as a string; the
* statusVariable out-parameter is unreliable.
*
* Proves:
* 1. return_type is string: typeof the result is "string", NOT "number".
* 2. The returned string is the actual response BODY — it matches the body
* HTTP.Get reports under its .Content field for the same URL.
* 3. DEVIATION marked "DEV": the official Salesforce docs describe the
* return value as a NUMERIC STATUS. It is not a number, and it is not
* even a numeric-looking string — Number(result) is NaN for a text body.
* 4. DEVIATION marked "DEV": statusVariable was meant to carry the numeric
* status as statusVariable[0]. On a successful call it is observed
* EMPTY: statusVariable.length === 0 and statusVariable[0] === undefined.
* 5. The returned value is a real JS string, so ordinary string operations
* work on it (length, indexOf, substring, charAt).
*
* SCOPE: evidence gathered on a CloudPage GET only.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
var URL = "https://ssjs.guide/robots.txt";
/* 1 + 3. It is a string body, not a numeric status. */
var status = [];
var result = Platform.Function.HTTPGet(URL, false, 0, null, null, status);
assert("typeof the return value is string", String(typeof result), "string");
assert("DEV typeof is NOT number (docs: a numeric status)", String(typeof result) === "number" ? "true" : "false", "false");
assert("DEV the value is not a numeric status code (docs: e.g. 200)", result === "200" ? "true" : "false", "false");
assert("DEV Number(result) is NaN - it is body text, not a status", isNaN(Number(result)) ? "true" : "false", "true");
/* 2. It really is the response body. */
var r = HTTP.Get(URL);
assert("the value equals the body HTTP.Get reports under .Content", result === String(r.Content) ? "true" : "false", "true");
assert("the body is non-empty", result.length > 0 ? "true" : "false", "true");
/* 4. DEVIATION — the statusVariable out-parameter stays empty. */
assert("DEV statusVariable.length === 0 on success (docs: holds the status)", String(status.length), "0");
assert("DEV statusVariable[0] === undefined on success (docs: the number)", String(typeof status[0]), "undefined");
assert("DEV statusVariable[0] is not 200", status[0] === 200 ? "true" : "false", "false");
/* 5. It behaves as an ordinary JS string. */
assert("the value supports .length", String(typeof result.length), "number");
assert("the value supports .indexOf", String(typeof result.indexOf("x")), "number");
assert("substring(0, 0) returns the empty string", result.substring(0, 0), "");
assert("charAt(0) returns a 1-character string", String(result.charAt(0).length), "1");
assert("the value round-trips through String()", String(result) === result ? "true" : "false", "true");
</script>