Google Apps Script

HTML Service: Restrictions

To protect users from being served malicious HTML or JavaScript, Apps Script relies on the Caja Compiler to sanitize and sandbox HTML-service web apps or custom user interfaces for Google Docs, Sheets, and Forms. (The HTML service does not use Caja in other situations, like generating the body of an email.) Caja’s sanitization process detects some security violations before even showing the page, and an in-browser sandbox prevents other actions on the fly. Caja sanitization does impose some limitations on your code, however.

Sandbox Mode

You can use the setSandboxMode() method to choose between two versions of Caja: NATIVE mode imposes fewer restrictions than EMULATED mode and generally runs faster. By contrast, EMULATED mode is more likely to work in older browsers that do not support ECMAScript 5 strict mode, most notably Internet Explorer 9. (Very old browsers, including Internet Explorer 8 and below, are usually incompatible with the HTML service.)

If a script does not set a sandbox mode, Apps Script uses NATIVE mode as the default. Prior to February 2014, the default was EMULATED.

Note that setSandboxMode does not guarantee that the script will use that mode for all browsers: If NATIVE mode is set but not supported in the user's browser, the sandbox mode automatically falls back to EMULATED for that browser.

The example below shows how to set the sandbox mode, as well as how to determine which sandbox mode the browser is actually using by inspecting the property google.script.sandbox.mode. index.html
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index')


The HTML service produces HTML5 web pages, but only from a markup perspective. In other words, the HTML service supports most HTML5 elements and attributes, but not new APIs like web storage.

Naming restrictions

Like CSS and client-side JavaScript identifiers, no element’s name or ID can end with __ (two underscores).

Element restrictions

Although embed, iframe, and object elements are technically supported, their content is severely restricted; in practical terms, you cannot use these elements.

Anchor tags

Anchor tags in HTML-service pages partially hide the referer from the link's destination. If you link to a page on another server that logs its referers, that server will know that the link came from the Apps Script server, but not from which script specifically.

Also, anchor tags in web apps can only set the _blank and _self targets. Anchor tags in custom user interfaces for Google Docs, Sheets, or Forms can only set the _blank target.


Apps Script allows HTML forms to submit either back to the script or to another server, but, as with anchor tags, forms partially hide the referer from the form’s destination. Thus, if you submit a form to a page on another server that logs its referers, that server will know that the form came from the Apps Script server, but not from which script specifically.

If you’re submitting a form to Apps Script and want to receive an AJAX-like response without redirecting the page, use the special syntax described in the forms section of the google.script guide.


A small number of restrictions apply to CSS in HTML-service pages.

Adding CSS dynamically

In the EMULATED sandbox mode, scripts cannot add link elements at runtime that load in new external stylesheets after Caja has already processed the page. This restriction does not apply in NATIVE mode.

Naming restrictions

As with HTML elements and client-side JavaScript identifiers, CSS identifiers cannot end with __ (two underscores).

Double-colon notation

Pseudo-selectors that use double-colon notation (like ::after) are not currently supported. Instead, use the single-colon equivalent (like :after).

Fixed positioning

The CSS declaration position: fixed is not allowed.

Orphans and widows

The orphans and widows properties are not allowed.


The :nth-child() pseudo-selector is not currently supported.

Obscure CSS3 features

A few obscure or non-standardized CSS3 features are not supported. To check whether Caja supports a specific feature, see the CSS whitelist definitions in Caja's public repository. Additionally, Caja supports some CSS3 properties but not all values for those properties, which may not be obvious from the whitelists. It's usually simplest just to try using the property or value you want, then inspect the rendered page to see whether the CSS made it through.


Rewritten code

In the EMULATED sandbox mode, Caja inspects and substantially rewrites all HTML and JavaScript before the page loads. This results in a substantial slowdown in loading times relative to the newer NATIVE mode. Because code is rewritten, it also becomes difficult to debug.

In NATIVE mode, although comments are still stripped from client-side code, the code is only rewritten if it contains variables or named functions at the top level, or if it uses the typeof operator to refer to a variable directly. The examples below show how to avoid code rewrites in NATIVE mode.

Don't — code will be rewritten Do — code will not be rewritten in NATIVE mode
  var x = 3;
  function foo() { ... }
  window.x = 3; = function() { ... };
    if (typeof y === 'undefined') { ... }
    function bar(a) {
      if (typeof a === 'object') { ... }
    if (typeof window.y === 'undefined') { ... }
    function bar(a) {
      var o = { a: a };
      if (typeof o.a === 'object') { ... }

Strict mode

Client-side JavaScript in HTML-service pages must use “strict” JavaScript, which, among other things, requires that variables be declared before use, forbids the with keyword and delete variable (while still allowing delete, and removes the arguments.callee reference within functions. In addition, your code cannot use eval (even though strict mode normally allows it). Note that these restrictions apply even if the user’s browser doesn't natively support strict mode. The use strict directive is optional, although still good practice.

Adding scripts dynamically

In the EMULATED sandbox mode, scripts cannot insert other scripts at runtime. All JavaScript code must be available during the pre-processing stage to ensure it complies with the security constraints. This imposes several restrictions: scripts cannot create script elements; scripts cannot dynamically add statements to a button's onclick attribute (although they can add the name of an existing function to the onclick attribute); and the JSONP technique is not allowed (although XMLHttpRequests are allowed). None of these restrictions apply in NATIVE mode.

External JavaScript libraries

You can include external JavaScript libraries in your code via script elements as you would expect. These libraries are subject to the same sandbox restrictions and potential rewriting as your own client-side code; many JavaScript libraries work, but not all will. Complex libraries are more likely to work in NATIVE mode than in EMULATED mode.

jQuery and jQuery UI

All recent versions of the jQuery and jQuery UI libraries are compatible with Caja, but the libraries load faster if you use the versions that Google hosts:

  • jQuery: <script src="//"></script>
  • jQuery UI: <script src="//"></script>

Browser access

Your JavaScript does not have full access to the surrounding browser. You cannot, for example, read cookies, navigate the history, or set the title of the window (although you can set it initially via the HtmlOutput object’s setTitle() method).

Naming restrictions

As with CSS and HTML elements, no identifier in client scripts can end with __ (two underscores). Because this restriction does not apply in server-side Apps Script code, it’s important to make sure that you don't send objects from the server to the client that contain illegal properties. If you use a JavaScript object as a map from strings to objects, where the keys are potentially any strings, append a character of your own to the end of each string so that you don't unexpectedly use an illegal key.


Your code cannot reassign JavaScript primitive objects such as Array, Boolean, Infinity, NaN, Number, Object, RegExp, and String, and cannot assign new properties to these objects or their prototypes.


In EMULATED mode, document.documentElement is null if a page contains only script or style elements.

Error objects

The stack property of Error objects is always undefined.


The WeakMap object is provided in Caja even though it is not part of ECMAScript 5.



Because the HTML service cannot read or transmit cookies, externally hosted scripts and other resources referenced in HTML files must be publicly accessible without authentication cookies.

URL proxying

Caja proxies most content retrieved via URL (including external URLs specified in img, link, or script elements) and may modify or disallow requests for security reasons. The limitations are more strict in EMULATED mode.

XMLHttpRequests (XHR)

XMLHttpRequests to other servers are allowed — either without authentication or using an authorization header — provided those servers set appropriate CORS headers and are willing to accept requests from outside their domain. The syntax for XHRs is standardized to use XMLHttpRequest even in Internet Explorer. However, the method getResponseXML() is not supported.

XHR requests to the Google Apps Script server are forbidden, but you can use to make AJAX-like requests to your script instead.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.