Documentation
Gear Browser supports two extension models on iOS: Web Extension and UserScript, to extend browser functionality.
Web Extension
Supports Web Extensions based on the Manifest v3 model and the iOS Web Extension runtime exposed by WebKit.
Because extension resource schemes may differ across platforms, browser.runtime.getURL() is recommended instead of relying on chrome-extension:// or webkit-extension:// directly.
References
UserScript
The built-in, high-performance UserScript engine is compatible with Tampermonkey, Greasemonkey, and Violentmonkey.
All metadata and GM_* / GM.* APIs are documented below.
UserScript quick start
A minimal UserScript template to get started quickly.
// ==UserScript==
// @name {{name}}
// @version 0.1
// @description New UserScript
// @author You
// @match *
// @run-at document-end
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Your code here...
})();
UserScript headers
Supported metadata fields, matching rules, grants, and resource declarations.
-
@name
The name of the UserScript. Supports localization.
// @name My Script // @name:jp 私のスクリプト -
@namespace
The namespace of the UserScript.
-
@version
The version of the UserScript. Increase this number whenever the script changes so Gear can determine whether an update is available.
-
@author
The author of the UserScript. It appears in the script detail view.
-
@description
The description of the UserScript. It appears in the add-on list. Supports localization.
// @description Improve web page speed // @description:jp ウェブページの速度を改善する -
@homepage
The homepage URL of the script.
-
@icon, @iconURL, @defaulticon
The icon of the UserScript. It appears in the add-on list.
// @icon https://www.example.com/icon.png // @icon data:image/gif;base64,R0lGODlhEAAQAMQAAOR... -
@icon64, @icon64URL
The high-resolution icon of the UserScript. Gear prefers this value when displaying the icon, if it is set.
// @icon64 https://www.example.com/icon.png // @icon64 data:image/gif;base64,R0lGODlhEAAQAMQAAOR... -
@updateURL
The URL used to check for script updates. Gear prefers this value when checking for new versions.
-
@downloadURL
The URL used to download the script. Gear uses this value for updates if
@updateURLis not set. If neither value is set, Gear reuses the original installation URL. -
@supportURL
The support URL for contacting the author. It is displayed in the add-on detail view.
-
@contributionURL
The contribution URL for donations or sponsorship. It is displayed in the add-on detail view.
-
@run-at
Defines when the script is injected.
-
document-start
The script will be injected as fast as possible.
-
document-body
The script will be injected if the body element exists.
-
document-end
The script is injected when or after the
DOMContentLoadedevent is dispatched. -
document-idle
The script is injected after the
DOMContentLoadedevent is dispatched. This is the default value if no@run-attag is given. -
context-menu
The script is injected when it is selected from the browser context menu.
-
-
@run-in
Defines the type of browser context in which the script will be injected.
-
normal-tabs
The script will be injected for normal tabs.
-
incognito-tabs
The script will be injected for private tabs only.
-
both
The script will be injected for both normal tabs and private tabs.
-
-
@include
The URL patterns on which the script will run. Gear prefers this value for matching.
Matches any URL that uses the http scheme
// @include http://*/*Will match: http://foo.bar/ http://example.org/foo/bar.html
Matches any URL that uses the HTTP scheme, on any host, as long as the path starts with /foo.
// @include http://*/foo*Will match: http://example.com/foo/bar.html http://abc.com/foo
Matches any URL that starts with http or https for foo.bar.
// @include *://foo.bar/Will match: http://foo.bar/ https://foo.bar
-
@match
Works like
@include. Gear uses this value if@includeis not set. -
@exclude, @exclude-match
The URL patterns on which the script should not run. The matching rules are the same as
@include. -
@require
The file will be loaded and executed before the script starts running.
// @require https://code.jquery.com/jquery-2.1.4.min.js // @require https://foo.bar/your_packing.js -
@resource
Access these resources with
GM_getResourceTextandGM_getResourceURL. Resources are downloaded and cached in advance.// @resource image https://www.example.com/image.png // @resource data https://www.example.com/data.json -
@connect
The allowed domains for
GM_xmlHttpRequest. -
@grant
The allowlist for
GM_*andGM.*APIs. See the grant group list below for details.// @grant GM_setValue // @grant GM_getValue // @grant GM_setClipboard // @grant unsafeWindow -
@webRequest
The JSON data that follows the rule format of
GM_webRequest.// @webRequest [{selector: 'https://example.com/*', action: 'cancel'}] -
@tag
Tags shown in the detail view.
// @tag productivity // @tag blocker // @tag social -
@license
License information for the script.
-
@noframes
Indicates that the script should run only in the top-level page, not in iframes.
-
@unwrap
The script is injected directly into the page without a wrapper. This allows direct access to global page variables and functions. The
@grantmeta key is ignored, andGM_*APIs are not available. -
@antifeature
Indicates that the script discloses monetized or potentially undesirable features.
// @antifeature type description // @antifeature ads This script contains ads. // @antifeature:jp ads このスクリプトには広告が含まれています。
GM APIs
Storage, network, resource, menu, tab, clipboard, audio, and notification APIs.
unsafeWindow
Storage
Set a value in storage.
GM_setValue(name, value) : void
GM.setValue(name, value) : Promise
Set multiple key-value pairs in storage.
GM_setValues(values) : void
GM.setValues(values) : Promise
GM_setValues({
"foo": "bar",
"key": "value"
});
await GM.setValues({
"foo": "bar",
"key": "value"
});
Get a value from storage. You can provide a default value if the key is not found.
GM_getValue(name, defaultValue) : any
GM.getValue(name, defaultValue) : Promise
Get multiple values from storage. You can also provide default values for missing keys.
GM_getValues(keys) : any
GM.getValues(keys) : Promise
const values = GM_getValues(['foo', 'bar']);
const asyncValues = await GM.getValues(['foo', 'bar']);
const defaultValues = GM_getValues({
"foo": 1,
"bar": 2
});
const asyncDefaultValues = await GM.getValues({
"foo": 1,
"bar": 2
});
Delete a value from storage.
GM_deleteValue(name) : void
GM.deleteValue(name) : Promise
Delete multiple values from storage.
GM_deleteValues(keys) : void
GM.deleteValues(keys) : Promise
GM_deleteValues(["foo", "bar"]);
await GM.deleteValues(["foo", "bar"]);
Return an array of keys stored for the script.
GM_listValues() : array
GM.listValues() : Promise
List, set, or delete cookies. (Experimental)
// All GM cookie APIs are experimental and may change in the future.
GM_cookie.list(details, callback) : void
GM.cookies.list(details) : Promise
const details = {
// url string?, The URL from which to retrieve cookies. If not specified, the current URL is used.
url: "https://gear4.app",
// domain string?, The domain of the cookies to retrieve.
domain: "gear4.app",
// name string?, The name of the cookies to retrieve.
name: "foo",
// path string?, The path of the cookies to retrieve.
path: "/"
};
GM_cookie.list(details, function(cookies, error) {
console.log(cookies);
});
const cookies = await GM.cookies.list(details)
console.log(cookies);
// ----------------------
GM_cookie.set(details, callback) : void
GM.cookies.set(details) : Promise
const details = {
// name string, The name of the cookie.
name: "foo",
// value string, The value of the cookie.
// url string?, The URL for the cookie. If not specified, the current URL is used.
url: "https://gear4.app",
// domain string?, The domain for the cookie.
domain: "gear4.app",
// path string?, The path for the cookie.
path: "/",
// secure bool?, Whether the cookie should be sent over HTTPS.
secure: true,
// httpOnly bool?, Whether the cookie should be marked as HTTPOnly.
httpOnly: false,
// expirationDate number?, The expiration date for the cookie.
expirationDate: 60 * 60 * 24 // Expires in one day.
};
GM_cookie.set(details, function () {
console.log('Set cookie successfully.');
});
GM.cookies
.set(details)
.then(() => {
console.log('Set cookie successfully.');
});
// ----------------------
GM_cookie.delete(details, callback) : void
const details = {
// url string?, The URL for the cookie. If not specified, the current URL is used.
url: "https://gear4.app",
// name string, The name of the cookie to delete.
name: "foo"
};
GM_cookie.delete(details, function(error) {
console.log('Delete cookie successfully');
});
Add a value change listener and return a listener ID. Remove it with GM_removeValueChangeListener(listenerId).
GM_addValueChangeListener(name, function(name, oldValue, newValue, isRemote)) : string
Remove a value change listener by listener ID.
GM_removeValueChangeListener(listenerId)
Insert a CSS style element into the document head.
GM_addStyle(style) : void
GM.addStyle(style) : void
Insert a new element into the document or a parent node, and return the element itself.
GM_addElement(parentNode, tagName, attributes) : node
GM_addElement(tagName, attributes) : node
GM_addElement('script', {
src: 'https://abc.com/script.js',
type: 'text/javascript'
});
GM_addElement(
document.head,
'script',
{
src: 'https://abc.com/script.js',
type: 'text/javascript'
}
);
Output a log message to the console.
GM_log(message) : void
GM.log(message) : void
Get the raw content defined by @resource.
GM_getResourceText(name) : String
Get the Base64-encoded URI defined by @resource.
GM_getResourceURL(name) : any
GM.getResourceUrl(name) : Promise
Register a menu command that can be accessed from the running add-on menu.
GM_registerMenuCommand(name, fn) : String
GM.registerMenuCommand(name, fn) : String
GM_registerMenuCommand(name, fn, accessKey) : String
GM.registerMenuCommand(name, fn, accessKey) : String
GM_registerMenuCommand(name, fn, options) : String
GM.registerMenuCommand(name, fn, options) : String
const menuAction = GM_registerMenuCommand("Show Menu", callback, {
// id number|string? The menu ID to return. If omitted, a new ID is generated automatically.
id: "menu",
// title string? A subtitle shown under the name.
title: "show the menu",
// autoClose: bool? Whether to close the menu when this item is tapped. Default is true.
autoClose: false,
// accessKey: string? The access key for the menu item. Not supported yet.
accessKey: "s"
});
// Use the returned ID with GM_unregisterMenuCommand to remove the menu item.
GM_unregisterMenuCommand(menuAction)
Unregister a menu command by its ID.
GM_unregisterMenuCommand(id) : void
GM.unregisterMenuCommand(id) : void
Open a new tab with options.
GM_openInTab(url, options) : TabObject
GM_openInTab(url, loadInBackground) : TabObject
TabObject = {
// The tab is closed or not.
'closed': Bool,
// The event handler will be called when the tab is closed.
'onclose': Function,
// The method to close the newly opened tab.
'close': Function
}
Create a new XMLHttpRequest-style request.
GM_xmlhttpRequest(options) : RequestObject
GM.xmlHttpRequest(options) : Promise
// Contains abort() to cancel the request. The onabort handler will be called.
RequestObject = {'abort': Function}
const request = GM_xmlhttpRequest({
// @required string: The destination URL. Relative paths are supported.
"url": "https://www.example.com",
// string (GET|POST|HEAD): The request method.
"method": "GET",
// Key-value object: Request headers.
"headers": {
"referer": "value"
},
// string | ArrayBuffer | Blob | DataView | FormData: Data to send with the request.
"data": "foo",
// Key-value object: Cookie data to send with the request.
"cookie": {
"foo": "bar"
},
// boolean: Whether to send data in binary mode.
"binary": false,
// boolean: Whether to send the request without using cache.
"nocache": false,
// boolean: Whether to revalidate cached content.
"revalidate": false,
// int: Timeout in milliseconds.
"timeout": 2000,
// any: A value added to the response object.
"context": [],
// string (text|json|blob|arraybuffer|document): The response data type.
"responseType": "text",
// string: The MIME type for the request.
"overrideMimeType": "text/plain",
// boolean: Whether to send the request without cookies.
"anonymous": false,
// string: The username for request authentication.
"user": "foo",
// string: The password for request authentication.
"password": "pwd",
// The event handlers.
"onabort": (event) => void,
"onerror": (event) => void,
"onload": (event) => void,
"onloadend": (event) => void,
"onloadstart": (event) => void,
"onprogress": (event) => void,
"onreadystatechange": (event) => void,
"ontimeout": (event) => void,
// The event object from handlers will contain the following attributes:
// "finalUrl" - The final URL after all redirects from where the data was loaded.
// "readyState" - The ready state.
// "status" - The request status.
// "statusText" - The request status text.
// "responseHeaders" - The response headers.
// "response" - The response data as an object if details.responseType was set.
// "responseXML" - The response data as an XML document.
// "responseText" - The response data as a plain string.
});
// Call this method to cancel the request.
request.abort()
// GM.xmlHttpRequest returns a Promise for async usage.
const response = await GM.xmlHttpRequest(options)
console.log(response.responseText)
Control audio state
GM_audio.setMute(details, callback?) : void
GM.audio.setMute(details, callback?) : Promise
GM_audio.getState(callback) : void
GM.audio.getState() : Promise
GM_audio.addStateChangeListener(listener, callback?) : void
GM.audio.addStateChangeListener(listener, callback?) : Promise
GM_audio.removeStateChangeListener(listener, callback?) : void
GM.audio.removeStateChangeListener(listener, callback?) : Promise
// Set the mute state for current tab.
GM_audio.setMute({
// @required boolean: true to mute the tab, false to unmute it.
"isMuted": true
}, (error) => {
if (error) {
console.error('mute failed:', error)
return
}
console.log('tab muted')
})
// Read the current audio state.
GM_audio.getState((state) => {
if (!state) {
console.error('failed to read state')
return
}
// boolean: Whether the tab is muted.
console.log('muted?', state.isMuted)
// string (user|capture|extension): The mute reason if the tab is muted.
console.log('mute reason:', state.muteReason)
// boolean: Whether the tab is currently playing audio.
console.log('audible?', state.isAudible)
})
// Listen for mute / audible changes.
function onAudioStateChange(event) {
// string | false: Mute reason, or false if not muted.
if ('muted' in event) {
console.log('muted:', event.muted)
}
// boolean: Whether the tab is currently playing audio.
if ('audible' in event) {
console.log('audible:', event.audible)
}
}
GM_audio.addStateChangeListener(onAudioStateChange)
// Remove a previously registered listener.
GM_audio.removeStateChangeListener(onAudioStateChange, () => {
console.log('listener removed')
})
// Promise style examples.
await GM.audio.setMute({ isMuted: false })
const state = await GM.audio.getState()
console.log(`muted=${state.isMuted} reason=${state.muteReason} audible=${state.isAudible}`)
await GM.audio.addStateChangeListener((event) => {
if (event.muted) {
console.log('muted by', event.muted)
}
})
await GM.audio.removeStateChangeListener(onAudioStateChange)
Create a new download task.
GM_download(options), GM_download(url, name) : RequestObject
// Contains abort() to cancel the download request. The onabort handler will be called.
RequestObject = {'abort': Function}
const request = GM_download({
// @required string: The destination URL. Relative paths are supported.
"url": "https://www.example.com/file.mp3",
// @required string: The file name to save as.
"name": "my.mp3",
// Key-value object: Download request headers.
"headers": {
"referer": "value"
},
// boolean: Whether to show the Save As prompt.
"saveAs": false,
// int: Timeout in milliseconds.
"timeout": 2000,
// The event handlers.
"onerror": (event) => void,
"onprogress": (event) => void,
"ontimeout": (event) => void,
"onload": (event) => void,
// The event object from handlers will contain the following attributes:
// "finalUrl" - The final URL after all redirects from where the data was loaded.
// "readyState" - The ready state.
// "status" - The request status.
// "statusText" - The request status text.
// "responseHeaders" - The response headers.
// "response" - The response data as an object if details.responseType was set.
// "responseXML" - The response data as an XML document.
// "responseText" - The response data as a plain string.
});
// Call this method to cancel the download request.
request.abort()
Set the clipboard contents.
GM_setClipboard(data, info = 'text|html') : void
GM.setClipboard(data, info = 'text|html') : void
Get the current tab object.
// This function is currently unsupported.
GM_getTab
Save the current tab object.
// This function is currently unsupported.
GM_saveTab
Send a notification.
// GM_notification currently logs only the text and title to the console.
GM_notification(text, title, image, onclick)
Read script information.
// You don't need to declare this API on @grant to read this value.
console.log(GM_info)
[
"script": [
"uuid": string,
"name": string,
"author": string,
"description": string,
"namespace": string,
"homepage": string,
"version": string,
"icon": string,
"icon64": string,
"excludes": array,
"includes": array,
"matches": array,
"requires": array,
"resources": object,
"run-at": string,
"updateURL": string,
"downloadURL": string,
"supportURL": string,
],
"downloadMode": string = native,
"scriptMetaStr": string,
"scriptSource": string,
"scriptUpdateURL": string,
"scriptHandler": string = Tampermonkey,
"isIncognito": bool,
"version": string
]
Grant groups
Grant behavior and iOS compatibility notes for writing stable scripts.
GM. and GM_ are equivalent.- GM_getValue, GM_addValueChangeListener, GM_removeValueChangeListener, GM_listValues
- GM_setValue, GM_deleteValue
- GM_addStyle, GM_addElement
- GM_getResourceText, GM_getResourceURL, GM_getResourceUrl
- GM_getTab, GM_saveTab, GM_getTabs
- GM_registerMenuCommand, GM_unregisterMenuCommand
iOS compatibility
- WKWebView's RegExp engine did not support lookahead and lookbehind groups until iOS 16.4. This includes positive lookahead
(?=...), negative lookahead(?!...), positive lookbehind(?<=...), and negative lookbehind(?<!...). You may need to rewrite patterns that rely on these features. - See the API differences between Chrome and Safari at https://caniuse.com/?compare=chrome+101,safari+15.4&compareCats=HTML5,JS,JS%20API.
- Check ES5 and ES6 support across iOS versions at https://caniuse.com/?search=es5 and https://caniuse.com/?search=es6.