Using Userscripts on Mac and in Safari

Running userscripts on a Mac generally works the same as on any other platform, with the main exception being Safari, which has its own extension model. This covers what changes on macOS and iOS, and how to debug a script that misbehaves in Safari specifically.
Chrome and Firefox on macOS behave the same as elsewhere
If you use Chrome or Firefox on a Mac, Tampermonkey and Violentmonkey install and work exactly as they do on Windows or Linux. There is no macOS-specific limitation in these browsers, and scripts installed from the HatScripts /userscripts hub run identically across platforms.
Safari’s extension model is different
Safari extensions are distributed through the Mac App Store and built using Apple’s Safari Web Extension format, which wraps a native app around the extension code. This is a stricter distribution model than Chrome or Firefox use, and it is why fewer userscript managers exist for Safari, and why the ones that do exist are sometimes paid.
Apple’s review process for App Store listings adds a delay between a new manager release and its availability to users, which is different from Chrome and Firefox stores, where extension updates typically appear within a day or two of being published. This can mean a Safari userscript manager lags a version or two behind its Chrome counterpart at any given time.
Tampermonkey for Safari
Tampermonkey publishes a Safari version through the Mac App Store. Unlike its free Chrome and Firefox builds, the Safari version requires a paid license to unlock full functionality, since Apple’s distribution model does not support the same free extension approach used elsewhere.
The Userscripts app alternative
The Userscripts app, sometimes referred to by its earlier name, is a free, open source Safari extension built specifically around Apple’s newer extension APIs. It supports the standard @match, @grant and GM_ conventions that most userscripts already use, making it a practical free alternative to a paid Tampermonkey license on Safari.
Because it is open source, you can review exactly how it implements the GM_ API surface, which is useful if a specific script behaves differently on Safari than it does on Chrome and you want to confirm whether the difference comes from the manager or from Safari itself.
iOS Safari support
Both Tampermonkey and the Userscripts app extend to iOS and iPadOS, since Apple allows Safari Web Extensions to run on those platforms using the same underlying technology as the desktop build. Installation happens through the Settings app, where you enable the extension for Safari and grant it permission for the websites you want it to run on.
Mobile Safari’s per-site permission prompts are more prominent than on desktop, so expect to confirm access the first time a script tries to run on a new domain.
Permission prompts
Safari asks you to grant a userscript manager access to specific websites, either all websites or a chosen list, and this can be set to always allow, allow for a day, or ask every time. If a script that worked yesterday suddenly stops running, check whether a daily permission grant has simply expired.
Debugging with Web Inspector
Safari’s Web Inspector, enabled from Preferences under the Advanced tab, gives you a console and network panel similar to Chrome DevTools. Errors thrown by a userscript appear in this console, often tagged with the script’s own name if the manager logs consistently, which makes it possible to isolate whether a failure comes from the script itself or from Safari’s extension permission handling.
On iOS, Web Inspector requires connecting the device to a Mac and enabling it from Safari’s Develop menu on the desktop side, since iOS Safari has no on-device developer console of its own.
Common macOS-specific troubleshooting steps
A short checklist tends to resolve most Mac and Safari specific problems.
- Confirm the extension is actually enabled in Safari Preferences under the Extensions tab, since installing the app alone does not enable it in Safari
- Check per-site permissions have not reverted to Ask or Deny after a browser restart
- Confirm Safari’s version supports the manifest version the extension expects, since older macOS releases can be stuck on older Safari versions
- Restart Safari fully after granting a new website permission, since some permission changes only take effect after a relaunch
- On iOS, confirm the extension toggle in Settings under Safari Extensions is switched on, separate from having the app installed
Performance notes on Safari specifically
Safari’s WebKit engine handles content script injection somewhat differently from Chromium and Firefox’s Gecko engine, and in practice this rarely causes a noticeable slowdown for typical userscripts. Scripts that make heavy use of GM_xmlhttpRequest with many simultaneous requests are the more likely place to notice a difference, since Safari’s extension background page model has historically been more conservative about how long background contexts stay alive between requests.
A worked example: getting a script running on Safari for the first time
Suppose you have used a userscript in Chrome for months and switch to Safari as your main browser. Install the Userscripts app from the App Store, then open Safari Preferences, go to the Extensions tab, and enable it there, since installing the app alone does not activate it inside Safari. Next, open the script’s .user.js file or its hub link in Safari, confirm the metadata shown matches what you expect, and grant the extension access to the specific site listed in its @match pattern rather than granting access to every website by default.
If the script uses GM_xmlhttpRequest and lists an @connect domain, expect a separate permission step the first time it actually makes that request, similar to the site access prompt but scoped to network activity specifically.
Version and update checks on Safari
Update checking works the same conceptually on Safari as elsewhere: the manager compares the installed @version against what is found at @updateURL and prompts you to review a diff before applying it. The practical difference is timing. Because Safari extensions update through the App Store rather than a browser-specific store, the manager application itself may lag behind its Chrome counterpart by a release or two, even though script-level updates for individual userscripts are unaffected by this and continue to work through the same @updateURL mechanism regardless of platform.
Security review habits specific to Safari
Because Safari’s per-site permission model is more visible than Chrome’s, use it actively rather than granting access to every website out of convenience. Choosing a specific site or a short-lived grant for a script you are trying for the first time limits the blast radius if the script turns out to behave unexpectedly, and Safari makes it easy to review and revoke these grants later from the same Preferences screen.
- Grant a new script access to the specific site it needs rather than all websites, when Safari offers the choice
- Periodically review the Extensions tab to see which sites have standing access and revoke any you no longer need
- Treat a sudden expired-permission failure as expected behaviour rather than a bug, since Safari’s daily grants are designed to lapse
Writing scripts with Safari in mind
If you write your own userscripts and want them to behave consistently on Safari as well as Chrome and Firefox, avoid relying on GM_ functions that are newer or less commonly implemented, since Safari-side managers sometimes lag on the newest additions to the shared GM_ specification. Testing a script on Safari specifically, rather than assuming Chrome behaviour transfers directly, catches these gaps before they surprise a user.
Keeping @match patterns narrow also helps on Safari, since its per-site permission prompts are more visible to the end user than Chrome’s upfront install-time permission grant, and a narrower pattern means fewer separate site prompts for someone installing your script for the first time.
Frequently asked questions
Can I sync scripts between a Mac’s Safari and Chrome? Not directly through Safari’s sync features, since each manager keeps its own storage. Export from one manager and import into the other manually if you need the same script in both browsers.
Does Violentmonkey work on Safari at all? No, Violentmonkey has no official Safari build, so Safari users need Tampermonkey or the Userscripts app.
Why does a script work on Chrome but not on Safari? The most common cause is a GM_ API the Safari-side manager has not implemented, or a permission prompt on a specific domain that has not been granted. Checking Web Inspector’s console is the fastest way to confirm which of the two it is.
Questions about the tools in this guide
Short answers about the hubs this article touches, each linking straight to the tool.