To use the chrome.scripting
API, declare the "scripting"
permission in the manifest plus the host permissions for the pages to inject scripts into. Use the "host_permissions"
key or the "activeTab"
permission, which grants temporary host permissions. The following example uses the activeTab permission.
{ "name":"Scripting Extension", "manifest_version":3, "permissions":["scripting","activeTab"], ...}
You can use the chrome.scripting
API to inject JavaScript and CSS into websites. This is similar to what you can do with content scripts. But by using the chrome.scripting
namespace, extensions can make decisions at runtime.
You can use the target
parameter to specify a target to inject JavaScript or CSS into.
The only required field is tabId
. By default, an injection will run in the main frame of the specified tab.
functiongetTabId(){...}chrome.scripting.executeScript({target:{tabId:getTabId()},files:["script.js"],}).then(()=>console.log("script injected"));
To run in all frames of the specified tab, you can set the allFrames
boolean to true
.
functiongetTabId(){...}chrome.scripting.executeScript({target:{tabId:getTabId(),allFrames:true},files:["script.js"],}).then(()=>console.log("script injected in all frames"));
You can also inject into specific frames of a tab by specifying individual frame IDs. For more information on frame IDs, see the chrome.webNavigation
API.
functiongetTabId(){...}chrome.scripting.executeScript({target:{tabId:getTabId(),frameIds:[frameId1,frameId2]},files:["script.js"],}).then(()=>console.log("script injected on target frames"));
Extensions can specify the code to be injected either via an external file or a runtime variable.
Files are specified as strings that are paths relative to the extension's root directory. The following code will inject the file script.js
into the main frame of the tab.
functiongetTabId(){...}chrome.scripting.executeScript({target:{tabId:getTabId()},files:["script.js"],}).then(()=>console.log("injected script file"));
When injecting JavaScript with scripting.executeScript()
, you can specify a function to be executed instead of a file. This function should be a function variable available to the current extension context.
functiongetTabId(){...}functiongetTitle(){returndocument.title;}chrome.scripting.executeScript({target:{tabId:getTabId()},func:getTitle,}).then(()=>console.log("injected a function"));
functiongetTabId(){...}functiongetUserColor(){...}functionchangeBackgroundColor(){document.body.style.backgroundColor=getUserColor();}chrome.scripting.executeScript({target:{tabId:getTabId()},func:changeBackgroundColor,}).then(()=>console.log("injected a function"));
You can work around this by using the args
property:
functiongetTabId(){...}functiongetUserColor(){...}functionchangeBackgroundColor(backgroundColor){document.body.style.backgroundColor=backgroundColor;}chrome.scripting.executeScript({target:{tabId:getTabId()},func:changeBackgroundColor,args:[getUserColor()],}).then(()=>console.log("injected a function"));
If injecting CSS within a page, you can also specify a string to be used in the css
property. This option is only available for scripting.insertCSS()
; you can't execute a string using scripting.executeScript()
.
functiongetTabId(){...}constcss="body { background-color: red; }";chrome.scripting.insertCSS({target:{tabId:getTabId()},css:css,}).then(()=>console.log("CSS injected"));
The results of executing JavaScript are passed to the extension. A single result is included per-frame. The main frame is guaranteed to be the first index in the resulting array; all other frames are in a non-deterministic order.
functiongetTabId(){...}functiongetTitle(){returndocument.title;}chrome.scripting.executeScript({target:{tabId:getTabId(),allFrames:true},func:getTitle,}).then(injectionResults=>{for(const{frameId,result}ofinjectionResults){console.log(`Frame ${frameId} result:`,result);}});
scripting.insertCSS()
does not return any results.
If the resulting value of the script execution is a promise, Chrome will wait for the promise to settle and return the resulting value.
functiongetTabId(){...}asyncfunctionaddIframe(){constiframe=document.createElement("iframe");constloadComplete=newPromise(resolve=>iframe.addEventListener("load",resolve));iframe.src="https://example.com";document.body.appendChild(iframe);awaitloadComplete;returniframe.contentWindow.document.title;}chrome.scripting.executeScript({target:{tabId:getTabId(),allFrames:true},func:addIframe,}).then(injectionResults=>{for(constframeResultofinjectionResults){const{frameId,result}=frameResult;console.log(`Frame ${frameId} result:`,result);}});
The following snippet contains a function that unregisters all dynamic content scripts the extension has previously registered.
asyncfunctionunregisterAllDynamicContentScripts(){try{constscripts=awaitchrome.scripting.getRegisteredContentScripts();constscriptIds=scripts.map(script=>script.id);returnchrome.scripting.unregisterContentScripts({ids:scriptIds});}catch(error){constmessage=["An unexpected error occurred while","unregistering dynamic content scripts.",].join(" ");thrownewError(message,{cause:error});}}
To try the chrome.scripting
API, install the scripting sample from the Chrome extension samples repository.
string[] optional
If specified, getRegisteredContentScripts
will only return scripts with an id specified in this list.
string optional
A string containing the CSS to inject. Exactly one of files
and css
must be specified.
string[] optional
The path of the CSS files to inject, relative to the extension's root directory. Exactly one of files
and css
must be specified.
StyleOrigin optional
The style origin for the injection. Defaults to 'AUTHOR'
.
Details specifying the target into which to insert the CSS.
The JavaScript world for a script to execute within.
"ISOLATED" "MAIN"
Specifies the isolated world, which is the execution environment unique to this extension.
Specifies the main world of the DOM, which is the execution environment shared with the host page's JavaScript.
string
The document associated with the injection.
number
The frame associated with the injection.
any optional
The result of the script execution.
boolean optional
Whether the script should inject into all frames within the tab. Defaults to false. This must not be true if frameIds
is specified.
string[] optional
The IDs of specific documentIds to inject into. This must not be set if frameIds
is set.
number[] optional
The IDs of specific frames to inject into.
number
The ID of the tab into which to inject.
boolean optional
If specified true, it will inject into all frames, even if the frame is not the top-most frame in the tab. Each frame is checked independently for URL requirements; it will not inject into child frames if the URL requirements are not met. Defaults to false, meaning that only the top frame is matched.
string[] optional
The list of CSS files to be injected into matching pages. These are injected in the order they appear in this array, before any DOM is constructed or displayed for the page.
string[] optional
Excludes pages that this content script would otherwise be injected into. See Match Patterns for more details on the syntax of these strings.
string
The id of the content script, specified in the API call. Must not start with a '_' as it's reserved as a prefix for generated script IDs.
string[] optional
The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.
boolean optional
Indicates whether the script can be injected into frames where the URL contains an unsupported scheme; specifically: about:, data:, blob:, or filesystem:. In these cases, the URL's origin is checked to determine if the script should be injected. If the origin is null
(as is the case for data: URLs) then the used origin is either the frame that created the current frame or the frame that initiated the navigation to this frame. Note that this may not be the parent frame.
string[] optional
Specifies which pages this content script will be injected into. See Match Patterns for more details on the syntax of these strings. Must be specified for registerContentScripts
.
boolean optional
Specifies if this content script will persist into future sessions. The default is true.
RunAt optional
Specifies when JavaScript files are injected into the web page. The preferred and default value is document_idle
.
ExecutionWorld optional
The JavaScript "world" to run the script in. Defaults to ISOLATED
.
any[] optional
The arguments to pass to the provided function. This is only valid if the func
parameter is specified. These arguments must be JSON-serializable.
string[] optional
The path of the JS or CSS files to inject, relative to the extension's root directory. Exactly one of files
or func
must be specified.
boolean optional
Whether the injection should be triggered in the target as soon as possible. Note that this is not a guarantee that injection will occur prior to page load, as the page may have already loaded by the time the script reaches the target.
Details specifying the target into which to inject the script.
ExecutionWorld optional
The JavaScript "world" to run the script in. Defaults to ISOLATED
.
void optional
A JavaScript function to inject. This function will be serialized, and then deserialized for injection. This means that any bound parameters and execution context will be lost. Exactly one of files
or func
must be specified.
The func
function looks like: () => {...}
The origin for a style change. See style origins for more info.
"AUTHOR" "USER"
chrome.scripting.executeScript(
injection: ScriptInjection,
callback?: function,
)
Injects a script into a target context. By default, the script will be run at document_idle
, or immediately if the page has already loaded. If the injectImmediately
property is set, the script will inject without waiting, even if the page has not finished loading. If the script evaluates to a promise, the browser will wait for the promise to settle and return the resulting value.
The details of the script which to inject.
function optional
The callback
parameter looks like: (results: InjectionResult[]) => void
Promise<InjectionResult[]>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.getRegisteredContentScripts(
filter?: ContentScriptFilter,
callback?: function,
)
Returns all dynamically registered content scripts for this extension that match the given filter.
ContentScriptFilter optional
An object to filter the extension's dynamically registered scripts.
function optional
The callback
parameter looks like: (scripts: RegisteredContentScript[]) => void
Promise<RegisteredContentScript[]>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.insertCSS(
injection: CSSInjection,
callback?: function,
)
Inserts a CSS stylesheet into a target context. If multiple frames are specified, unsuccessful injections are ignored.
The details of the styles to insert.
function optional
The callback
parameter looks like: () => void
Promise<void>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.registerContentScripts(
scripts: RegisteredContentScript[],
callback?: function,
)
Registers one or more content scripts for this extension.
Contains a list of scripts to be registered. If there are errors during script parsing/file validation, or if the IDs specified already exist, then no scripts are registered.
function optional
The callback
parameter looks like: () => void
Promise<void>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.removeCSS(
injection: CSSInjection,
callback?: function,
)
Removes a CSS stylesheet that was previously inserted by this extension from a target context.
The details of the styles to remove. Note that the css
, files
, and origin
properties must exactly match the stylesheet inserted through insertCSS
. Attempting to remove a non-existent stylesheet is a no-op.
function optional
The callback
parameter looks like: () => void
Promise<void>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.unregisterContentScripts(
filter?: ContentScriptFilter,
callback?: function,
)
Unregisters content scripts for this extension.
ContentScriptFilter optional
If specified, only unregisters dynamic content scripts which match the filter. Otherwise, all of the extension's dynamic content scripts are unregistered.
function optional
The callback
parameter looks like: () => void
Promise<void>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
chrome.scripting.updateContentScripts(
scripts: RegisteredContentScript[],
callback?: function,
)
Updates one or more content scripts for this extension.
Contains a list of scripts to be updated. A property is only updated for the existing script if it is specified in this object. If there are errors during script parsing/file validation, or if the IDs specified do not correspond to a fully registered script, then no scripts are updated.
function optional
The callback
parameter looks like: () => void
Promise<void>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-03-17 UTC.