HTML Service: Restrictions

To protect users from being served malicious HTML or JavaScript, Apps Script uses a security sandbox to sandbox HTML-service web apps or custom user interfaces for Google Docs, Sheets, and Forms. (The HTML service does not use a sandbox in other situations, like generating the body of an email.) The sandbox imposes limitations on client-side code.

Sandbox Mode

You can use the setSandboxMode method to choose between three versions of the HTML service security sandbox.

IFRAME mode imposes many fewer restrictions than the other sandbox modes and runs fastest, but does not work at all in certain older browsers, including Internet Explorer 9. 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. NATIVE mode is the middle ground. If NATIVE mode is set but not supported in the user's browser, the sandbox falls back to EMULATED mode for that user.

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. The default is subject to change.

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.


function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index')



Restrictions in IFRAME mode

The IFRAME sandbox mode is based on the iframe sandboxing feature in HTML5, using the allow-same-origin, allow-forms, allow-scripts, and allow-popups keywords.

HTTPS required for active content

"Active" content like scripts, external stylesheets, and XmlHttpRequests must be loaded over HTTPS, not HTTP.

Restrictions in NATIVE and EMULATED mode

The NATIVE and EMULATED sandbox modes are based on the Caja Compiler. 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 imposes more limitations on client-side code than the IFRAME sandbox does.


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

  var x = 3;
  function foo() { ... }
  window.x = 3;
  window.foo = function() { ... };

Do — code will not be rewritten in NATIVE mode

  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 object.property), 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:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></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 google.script.run to make AJAX-like requests to your script instead.

Send feedback about...

Apps Script