Import attributes
Baseline
2025
*
Newly available
Since April 2025, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
* Some parts of this feature may have varying levels of support.
Note:
A previous version of this proposal used the assert keyword instead of with. The assertion feature is now non-standard. Check the browser compatibility table for details.
The import attributes feature instructs the runtime about how a module should be loaded, including the behavior of module resolution, fetching, parsing, and evaluation. It's supported in import declarations, export...from declarations, and dynamic import().
Attributes can be attached to any kind of import/export from statement, including default import, namespace import, etc. They follow the module specifier string and start with the with keyword. When used with import(), the attributes are specified in the options parameter as the with property.
Syntax
import { names } from "module-name" with {};
import { names } from "module-name" with { key: "data" };
import { names } from "module-name" with { key: "data", key2: "data2" };
import { names } from "module-name" with { key: "data", key2: "data2", /* …, */ keyN: "dataN" };
export { names } from "module-name" with {};
export { names } from "module-name" with { key: "data" };
export { names } from "module-name" with { key: "data", key2: "data2" };
export { names } from "module-name" with { key: "data", key2: "data2", /* …, */ keyN: "dataN" };
Parameters
Exceptions
SyntaxError-
An unsupported
keywas specified in a static import. TypeError-
An unsupported
keywas specified in a dynamic import.
Note that specifying an unsupported value for a supported key may also result in an exception in some cases, depending on the key.
Description
Import attributes tell the runtime how a particular module should be loaded.
The primary use case is to load non-JS modules, such as JSON modules and CSS modules. Consider the following statement:
import data from "https://example.com/data.json";
On the web, each import statement results in a HTTP request. The response is then prepared into a JavaScript value and made available to the program by the runtime. For example, the response may look like this:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
...
{"name":"Maria"}
Modules are identified and parsed only according to their served media type (MIME type) — the file extension in the URL cannot be used to identify a file's type. In this case, the MIME type is application/json, which tells the browser that the file is JSON and must be parsed as JSON. If, for some reason (e.g., the server is hijacked or bogus), the media type in the server response is set to text/javascript (for JavaScript source), then the file would be parsed and executed as code. If the "JSON" file actually contains malicious code, the import declaration would unintentionally execute external code, posing a serious security threat.
Import attributes fix this problem by allowing the author to explicitly specify how a module should be validated.
In particular, the type attribute allows you to validate that the file is served with a particular media type, and fails the import if a different media type is used.
For example, the code above can be written to specify that the expected type is "json" and the import would fail if it was served with the text/javascript (or any media type other than application/json):
import data from "https://example.com/data.json" with { type: "json" };
The type attribute allows you to specify that modules are served as JSON or CSS (and implicitly as JavaScript).
Other attributes may also be supported, and can affect the behaviour of different parts of the loading process. A syntax error is thrown if an unknown attribute is used.
Standard attributes
The available attributes depend on the language and runtime environment.
The ECMAScript standard defines the type attribute with the value of "json".
The HTML specification also defines the type attribute with values "json" and "css" — these are the attributes that are supported in browser environments.
JSON Modules ({ type: "json" })
The json type indicates that the imported file must contain JSON.
You can load JSON from a file into the data object using the following code:
import data from "https://example.com/data.json" with { type: "json" };
If the file is served with any other media type than "application/json", the import will fail.
The type attribute changes how the module is fetched (the browser sends the request with header), but does not change how the module is parsed or evaluated. The runtime already knows to parse the module as JSON given the response MIME type. It only uses the attribute to do after-the-fact checking that the Accept: application/jsondata.json module is, in fact, a JSON module. For example, if the response header changes to Content-Type: text/javascript instead, the program will fail with a similar error as above.
The specification explicitly calls out type: "json" to be supported — if a module is asserted to be type: "json" and the runtime does not fail this import, then it must be parsed as JSON.
However, there's no behavior requirement otherwise: for imports without a type: "json" attribute, the runtime may still parse it as JSON if security is not an issue in this environment.
Browsers, on the other hand, implicitly assume that the module is JavaScript if the type is not specified, and fail if the module is not JavaScript (for example, JSON). This ensures that module types are always strictly validated and prevents any security risks.
Non-browser runtimes such as Node and Deno align with browser semantics and enforce type for JSON modules.
In other words, if you omit the type and attempt to import a file as "application/json" you will usually get an error like the following:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec.
CSS Modules ({ type: "css" })
The HTML spec defines the css type, which imports a stylesheet into a script as an CSSStyleSheet object.
The code below shows how you might import a style and add it to your document.
The import will throw an exception if example_styles.css is served with any media type other than "text/css".
import exampleStyles from "https://example.com/example_styles.css" with { type: "css" };
document.adoptedStyleSheets.push(exampleStyles);
Note that importing CSS modules into workers is usually not supported, because the CSSOM specification only exposes CSSStyleSheet in the window context.
Intended semantics for import attributes
An attribute can change the runtime's behavior at every stage of the module loading process:
-
Resolution: the attribute is part of the module specifier (the string in the
fromclause). Therefore, given the same string path, different attributes may lead to entirely different modules being loaded. For example, TypeScript supports theresolution-modeattribute.tsimport type { TypeFromRequire } from "pkg" with { "resolution-mode": "require", }; -
Fetching: for example, CSS modules are fetched with the
destinationset to"style", and JSON modules are fetched withdestination: "json". This means given the same destination URL, the server may still return different content. -
Parsing and evaluation: the runtime may use the attribute to determine how to parse and evaluate the module.
Examples
>Importing JSON modules with the type attribute
In data.json:
{
"name": "Shilpa"
}
In index.html:
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<script type="module">
import data from "./data.json" with { type: "json" };
const p = document.createElement("p");
p.textContent = `name: ${data.name}`;
document.body.appendChild(p);
</script>
</head>
<body></body>
</html>
Start a local HTTP server (see troubleshooting) and go to the index.html page. You should see Shilpa on the page.
Note:
JSON modules only have one default export. You cannot do named imports from them (like import { name } from "data.json").
Using import attributes with dynamic import
Import attributes are also accepted as the second parameter of the import() syntax.
const data = await import("./data.json", {
with: { type: "json" },
});
Note that, like static imports, dynamic imports are cached for the lifetime of the environment (e.g., a page or worker). If you expect this data to change (such as the latest news or a user's credits), use the Fetch API instead.
Specifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # prod-WithClause> |