Async JavaScript
Load independent scripts without blocking HTML parsing, executing them the moment they finish downloading.
Metrics
This technique can move up to 33% of LCP's share of the Lighthouse score.
This technique can move up to 67% of TBT's share of the Lighthouse score.
This technique does not move CLS.
This technique can move up to 67% of FCP's share of the Lighthouse score.
This technique can move up to 33% of SI's share of the Lighthouse score.
This technique does not move TTFB.
Overview
The async attribute on a <script> tag tells the browser to download the script in parallel with HTML parsing — just like defer — but execute it immediately when the download completes, regardless of document state. It is the right choice for self-contained scripts that do not depend on the DOM or on other scripts: analytics trackers, chat widgets, third-party pixels, and A/B testing libraries.
Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: CLS, TTFB.
The Problem
Without async or defer, every <script> tag in the <head> blocks HTML parsing until the browser has downloaded and fully executed the script. Even a 20 KB analytics library introduces a stall of 100–400 ms on slow connections. Multiplied across 5–10 tracking scripts, this can push First Contentful Paint past 2 seconds before a single pixel of content appears.
Performance Impact
LCP
Indirect
fewer main-thread blocks during parse means the LCP resource faces less competition
TBT
30–60%
download blocking eliminated for all async scripts in the head
FCP
100–400ms
HTML parser is no longer stalled waiting for script downloads
SI
Indirect
earlier FCP contributes to a faster visual fill of the viewport
Risk: Medium
async ignores execution order — scripts that depend on each other will break
How it works
01
Script downloads in parallel with HTML parsing
When the browser encounters
<script async src="…">, it queues the download and immediately continues parsing the HTML. No stall, no main-thread block during the download phase.02
Execution fires the moment the download completes
Unlike
defer, async scripts do not wait for the DOM to be ready. The moment the file arrives — which may be mid-parse — the parser pauses briefly, the script runs, then parsing resumes. This makes async scripts faster to execute but unpredictable in timing.03
No execution order guarantee
If you mark two async scripts A and B, whichever finishes downloading first runs first — even if A appeared before B in the HTML. Scripts that share state or have dependencies must use
deferinstead, which preserves source order.04
Best candidates for async
Analytics (Google Analytics, Plausible), chat widgets (Intercom, Crisp), third-party pixels (Facebook, LinkedIn), cookie consent scripts that do not block rendering, and any self-contained library that reads from or writes to its own namespace only.
Code Example
<!-- Blocks HTML parsing: downloaded and executed synchronously -->
<script src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script><!-- Downloads in parallel, executes immediately when ready -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>In WordPress, add async via the script_loader_tag filter: add_filter('script_loader_tag', function($tag, $handle){ if($handle === 'google-analytics') return str_replace(' src', ' async src', $tag); return $tag; }, 10, 2);
Limitations
- Has no effect on inline scripts — only external scripts with a
srcattribute are eligible. - Do not use async on scripts that manipulate the DOM during initial load or depend on jQuery being present — they will execute before the DOM is ready and before dependencies have loaded.
- Module scripts (
type="module") are deferred by default; addingasyncto a module script makes it behave like async (no order guarantee). - On HTTP/1.1 connections, parallel downloads are limited by the browser’s per-host connection cap. On HTTP/2 and HTTP/3, true multiplexing makes async more effective.
Common Mistakes
Using async on jQuery-dependent scripts
If a script calls $() or jQuery(), it must wait for jQuery to load first. Use defer on both jQuery and the dependent script so execution order is preserved.
Applying async when defer would be more appropriate
If execution order matters between your scripts — for example, a theme’s main JS file that other scripts extend — use defer. Reserve async for fully independent third-party scripts.
Marking async scripts that call document.write()
document.write() from an async script executes after the parser has moved on, which replaces the entire page document. Remove or rewrite any script using document.write() before making it async.