Living Standard — Last Updated 9 June 2025
Scripts allow authors to add interactivity to their documents.
Authors are encouraged to use declarative alternatives to scripting where possible, as declarative mechanisms are often more maintainable, and many users disable scripting.
For example, instead of using a script to show or hide a section to show more details, the
details
element could be used.
Authors are also encouraged to make their applications degrade gracefully in the absence of scripting support.
For example, if an author provides a link in a table header to dynamically resort the table, the link could also be made to function without scripts by requesting the sorted table from the server.
script
elementSupport in all current engines.
Support in all current engines.
src
attribute, depends on the value of the type
attribute, but must match
script content restrictions.src
attribute, the element must be either empty or contain only
script documentation that also matches script
content restrictions.type
— Type of script
src
— Address of the resource
nomodule
— Prevents execution in user agents that support module scripts
async
— Execute script when available, without blocking while fetching
defer
— Defer script execution
blocking
— Whether the element is potentially render-blocking
crossorigin
— How the element handles crossorigin requests
referrerpolicy
— Referrer policy for fetches initiated by the element
integrity
— Integrity metadata used in Subresource Integrity checks [SRI]
fetchpriority
— Sets the priority for fetches initiated by the element
[Exposed =Window ]
interface HTMLScriptElement : HTMLElement {
[HTMLConstructor ] constructor ();
[CEReactions ] attribute DOMString type ;
[CEReactions ] attribute USVString src ;
[CEReactions ] attribute boolean noModule ;
[CEReactions ] attribute boolean async ;
[CEReactions ] attribute boolean defer ;
[SameObject , PutForwards =value ] readonly attribute DOMTokenList blocking ;
[CEReactions ] attribute DOMString ? crossOrigin ;
[CEReactions ] attribute DOMString referrerPolicy ;
[CEReactions ] attribute DOMString integrity ;
[CEReactions ] attribute DOMString fetchPriority ;
[CEReactions ] attribute DOMString text ;
static boolean supports (DOMString type );
// also has obsolete members
};
The script
element allows authors to include dynamic script, instructions to the
user agent, and data blocks in their documents. The element does not represent content for the user.
Support in all current engines.
The script element has two core attributes. The type
attribute allows customization of the type of script
represented:
Omitting the attribute, setting it to the empty string, or setting it to a
JavaScript MIME type essence match means that the script is a classic
script, to be interpreted according to the JavaScript Script top-level production. Authors should omit the type
attribute instead of redundantly setting it.
Setting the attribute to an ASCII case-insensitive match for "module
" means that the script is a JavaScript module script, to
be interpreted according to the JavaScript Module top-level
production.
Setting the attribute to an ASCII case-insensitive match for "importmap
" means that the script is an import map, containing
JSON that will be used to control the behavior of module specifier resolution.
Setting the attribute to any other value means that the script is a data block, which is not processed by the user agent, but instead by author script or other tools. Authors must use a valid MIME type string that is not a JavaScript MIME type essence match to denote data blocks.
The requirement that data blocks
must be denoted using a valid MIME type string is in place to
avoid potential future collisions. Values for the type
attribute that are not MIME types, like "module
" or "importmap
", are used by the standard to denote types of scripts which have
special behavior in user agents. By using a valid MIME type string now, you ensure that your
data block will not ever be reinterpreted as a different script type, even in future user
agents.
The second core attribute is the src
attribute. It must only be specified for classic scripts and JavaScript module scripts, and denotes that instead of using the element's
child text content as the script content, the script will be fetched from the
specified URL. If src
is specified, it must be
a valid non-empty URL potentially surrounded by spaces.
Which other attributes may be specified on a given script
element is determined by
the following table:
nomodule
| async
| defer
| blocking
| crossorigin
| referrerpolicy
| integrity
| fetchpriority
| |
---|---|---|---|---|---|---|---|---|
External classic scripts | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Inline classic scripts | Yes | · | · | · | Yes* | Yes* | · | ·† |
External module scripts | · | Yes | · | Yes | Yes | Yes | Yes | Yes |
Inline module scripts | · | Yes | · | · | Yes* | Yes* | · | ·† |
Import maps | · | · | · | · | · | · | · | · |
Data blocks | · | · | · | · | · | · | · | · |
* Although inline scripts have no initial fetches, the crossorigin
and referrerpolicy
attribute on inline scripts affects the
credentials mode and referrer
policy used by module imports, including dynamic import()
.
† Unlike crossorigin
and referrerpolicy
, fetchpriority
does not affect module imports. See some discussion in issue #10276.
The contents of inline script
elements, or the external script resource, must
conform with the requirements of the JavaScript specification's Script or Module productions, for classic scripts and JavaScript module scripts respectively. [JAVASCRIPT]
The contents of inline script
elements for import
maps must conform with the import map authoring requirements.
When used to include data blocks, the data must be embedded
inline, the format of the data must be given using the type
attribute, and the contents of the script
element must conform to the requirements
defined for the format used.
The nomodule
attribute is a boolean attribute that prevents a script from being executed in user
agents that support module scripts. This allows selective
execution of module scripts in modern user agents and classic scripts in older user agents, as shown below.
Support in all current engines.
Support in all current engines.
The async
and
defer
attributes are
boolean attributes that indicate how the script should be
evaluated. There are several possible modes that can be selected using these attributes, depending
on the script's type.
For external classic scripts, if the async
attribute is present, then the classic script will be
fetched in parallel to parsing and evaluated as soon as it is available (potentially
before parsing completes). If the async
attribute is not
present but the defer
attribute is present, then the
classic script will be fetched in parallel and evaluated when the page has finished
parsing. If neither attribute is present, then the script is fetched and evaluated immediately,
blocking parsing until these are both complete.
For module scripts, if the async
attribute is present, then the module script and all its
dependencies will be fetched in parallel to parsing, and the module script will
be evaluated as soon as it is available (potentially before parsing completes). Otherwise, the
module script and its dependencies will be fetched in parallel to parsing and
evaluated when the page has finished parsing. (The defer
attribute has no effect on module scripts.)
This is all summarized in the following schematic diagram:
The exact processing details for these attributes are, for mostly
historical reasons, somewhat non-trivial, involving a number of aspects of HTML. The
implementation requirements are therefore by necessity scattered throughout the specification. The
algorithms below describe the core of this processing, but
these algorithms reference and are referenced by the parsing rules for script
start and end tags in HTML, in foreign content, and in XML, the
rules for the document.write()
method, the handling of scripting, etc.
When inserted using the document.write()
method, script
elements usually
execute (typically blocking further script execution or HTML parsing). When inserted using the
innerHTML
and outerHTML
attributes, they do not execute at all.
The defer
attribute may be specified even if the async
attribute is specified, to cause legacy web browsers that
only support defer
(and not async
) to fall back to the defer
behavior instead of the blocking behavior that
is the default.
The blocking
attribute is a blocking attribute.
The crossorigin
attribute is a CORS settings
attribute. For external classic scripts, it controls
whether error information will be exposed, when the script is obtained from other origins. For external module scripts,
it controls the credentials mode used for
the initial fetch of the module source, if cross-origin. For both classic and module scripts, it controls the
credentials mode used for cross-origin
module imports.
Unlike classic scripts, module scripts require the use of the CORS protocol for cross-origin fetching.
The referrerpolicy
attribute is a referrer
policy attribute. Its sets the referrer policy used for the initial fetch of
an external script, as well as the fetching of any imported module scripts.
[REFERRERPOLICY]
An example of a script
element's referrer policy being used when fetching
imported scripts but not other subresources:
< script referrerpolicy = "origin" >
fetch( '/api/data' ); // not fetched with " as "\x3C/script
" when these sequences appear
in literals in scripts (e.g. in strings, regular expressions, or comments), and to avoid writing
code that uses such constructs in expressions. Doing so avoids the pitfalls that the restrictions
in this section are prone to triggering: namely, that, for historical reasons, parsing of
script
blocks in HTML is a strange and exotic practice that acts unintuitively in the
face of these sequences.
The script
element's descendant text content must match the script
production in the following ABNF, the character set for which is Unicode.
[ABNF]
script = outer * ( comment-open inner comment-close outer )
outer = < any string that doesn 't contain a substring that matches not-in-outer >
not-in-outer = comment-open
inner = < any string that doesn 't contain a substring that matches not-in-inner >
not-in-inner = comment-close / script-open
comment-open = ""
script-open = "<" s c r i p t tag-end
s = %x0053 ; U+0053 LATIN CAPITAL LETTER S
s =/ %x0073 ; U+0073 LATIN SMALL LETTER S
c = %x0043 ; U+0043 LATIN CAPITAL LETTER C
c =/ %x0063 ; U+0063 LATIN SMALL LETTER C
r = %x0052 ; U+0052 LATIN CAPITAL LETTER R
r =/ %x0072 ; U+0072 LATIN SMALL LETTER R
i = %x0049 ; U+0049 LATIN CAPITAL LETTER I
i =/ %x0069 ; U+0069 LATIN SMALL LETTER I
p = %x0050 ; U+0050 LATIN CAPITAL LETTER P
p =/ %x0070 ; U+0070 LATIN SMALL LETTER P
t = %x0054 ; U+0054 LATIN CAPITAL LETTER T
t =/ %x0074 ; U+0074 LATIN SMALL LETTER T
tag-end = %x0009 ; U+0009 CHARACTER TABULATION (tab)
tag-end =/ %x000A ; U+000A LINE FEED (LF)
tag-end =/ %x000C ; U+000C FORM FEED (FF)
tag-end =/ %x0020 ; U+0020 SPACE
tag-end =/ %x002F ; U+002F SOLIDUS (/)
tag-end =/ %x003E ; U+003E GREATER-THAN SIGN (>)
When a script
element contains script documentation, there are
further restrictions on the contents of the element, as described in the section below.
The following script illustrates this issue. Suppose you have a script that contains a string,
as in:
const example = 'Consider this string:
< script >
... // this is the same script block still...
script >
What is going on here is that for legacy reasons, "
< script >
... // this is a new script block
script >
It is possible for these sequences to naturally occur in script expressions, as in the
following examples:
if ( x