Skip to main content
HTML Validation

Element “script” must not have attribute “async” unless attribute “src” is also specified or unless attribute “type” is specified with value “module”.

About This HTML Issue

The async attribute tells the browser to download and execute a script without blocking HTML parsing. For external scripts (those with a src attribute), this means the browser can continue parsing the page while fetching the file, then execute the script as soon as it’s available. For inline module scripts (type="module"), async changes how the module’s dependency graph is handled — the module and its imports execute as soon as they’re all ready, rather than waiting for HTML parsing to complete.

For a classic inline script (no src, no type="module"), there is nothing to download asynchronously. The browser encounters the code directly in the HTML and executes it immediately. Applying async in this context is meaningless and contradicts the HTML specification, which is why the W3C validator flags it as an error.

Beyond standards compliance, using async incorrectly can signal a misunderstanding of script loading behavior, which may lead to bugs. For example, a developer might mistakenly believe that async on an inline script will defer its execution, when in reality it has no effect and the script still runs synchronously during parsing.

How to Fix

You have several options depending on your intent:

  1. If the script should be external, move the code to a separate file and reference it with the src attribute alongside async.
  2. If the script should be an inline module, add type="module" to the <script> tag. Note that module scripts are deferred by default, and async makes them execute as soon as their dependencies are resolved rather than waiting for parsing to finish.
  3. If the script is a plain inline script, simply remove the async attribute — it has no practical effect anyway.

Examples

❌ Invalid: async on a classic inline script

<script async>
  console.log("Hello, world!");
</script>

This triggers the validator error because there is no src attribute and the type is not "module".

✅ Fixed: Remove async from the inline script

<script>
  console.log("Hello, world!");
</script>

✅ Fixed: Use async with an external script

<script async src="app.js"></script>

The async attribute is valid here because the browser needs to fetch app.js from the server, and async controls when that downloaded script executes relative to parsing.

✅ Fixed: Use async with an inline module

<script async type="module">
  import { greet } from "./utils.js";
  greet();
</script>

This is valid because module scripts have a dependency resolution phase that can happen asynchronously. The async attribute tells the browser to execute the module as soon as all its imports are resolved, without waiting for the document to finish parsing.

❌ Invalid: async with type="text/javascript" (not a module)

<script async type="text/javascript">
  console.log("This is still invalid.");
</script>

Even though type is specified, only type="module" satisfies the requirement. The value "text/javascript" is the default classic script type and does not make async valid on an inline script.

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?
🌍 Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
$7 / 7 days

Pro Trial

Full Pro access. Cancel anytime.

Start Pro Trial →

Join teams across 40+ countries