{"id":15357424,"url":"https://github.com/simonalling/userscript-proxy","last_synced_at":"2025-06-20T19:38:03.297Z","repository":{"id":53568789,"uuid":"109727492","full_name":"SimonAlling/userscript-proxy","owner":"SimonAlling","description":"Browser extensions on any device","archived":false,"fork":false,"pushed_at":"2025-05-28T22:32:31.000Z","size":177,"stargazers_count":78,"open_issues_count":7,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-28T22:37:53.796Z","etag":null,"topics":["mitmproxy","userscript"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimonAlling.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":"FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"alling"}},"created_at":"2017-11-06T17:29:44.000Z","updated_at":"2025-05-28T22:32:35.000Z","dependencies_parsed_at":"2024-12-25T11:16:32.543Z","dependency_job_id":"6fdbcbe8-7585-40d6-9ccb-742c6272549e","html_url":"https://github.com/SimonAlling/userscript-proxy","commit_stats":{"total_commits":206,"total_committers":3,"mean_commits":68.66666666666667,"dds":0.01941747572815533,"last_synced_commit":"048067f5bda9a7f2e4efc5b96de84052ff1fa7c0"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/SimonAlling/userscript-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonAlling%2Fuserscript-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonAlling%2Fuserscript-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonAlling%2Fuserscript-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonAlling%2Fuserscript-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimonAlling","download_url":"https://codeload.github.com/SimonAlling/userscript-proxy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonAlling%2Fuserscript-proxy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261005798,"owners_count":23095920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mitmproxy","userscript"],"created_at":"2024-10-01T12:35:01.183Z","updated_at":"2025-06-20T19:37:58.283Z","avatar_url":"https://github.com/SimonAlling.png","language":"Python","readme":"# Userscript Proxy\n\nBrowser extensions on iOS, Android and pretty much any other web browsing device.\nNo jailbreak/root required.\n\nUserscript Proxy is built around [mitmproxy][mitmproxy] and acts as a MITM, injecting userscripts into web pages as they flow through it.\nBoth HTTP and HTTPS are supported.\n\n\u003c!--ts--\u003e\n   * [Userscript Proxy](#userscript-proxy)\n   * [Getting started](#getting-started)\n      * [Security notice](#security-notice)\n      * [Starting the proxy](#starting-the-proxy)\n      * [On a mobile device](#on-a-mobile-device)\n      * [HTTPS](#https)\n         * [Android](#android)\n         * [iOS](#ios)\n      * [Deploying userscripts](#deploying-userscripts)\n   * [Apps with certificate pinning](#apps-with-certificate-pinning)\n      * [Basic pattern](#basic-pattern)\n         * [Examples](#examples)\n      * [Regular expression](#regular-expression)\n         * [Examples](#examples-1)\n   * [Data usage](#data-usage)\n   * [Userscript compatibility](#userscript-compatibility)\n   * [Options](#options)\n      * [--bypass-csp ALLOW](#--bypass-csp-allow)\n      * [--inline, -i](#--inline--i)\n      * [--list-injected, -l](#--list-injected--l)\n      * [--no-default-rules](#--no-default-rules)\n      * [--no-default-userscripts](#--no-default-userscripts)\n      * [--port PORT, -p PORT](#--port-port--p-port)\n      * [--query-param-to-disable PARAM, -q PARAM](#--query-param-to-disable-param--q-param)\n      * [--rules FILE](#--rules-file)\n      * [--transparent, -t](#--transparent--t)\n      * [--userscripts-dir DIR, -u DIR](#--userscripts-dir-dir--u-dir)\n   * [Contribute](#contribute)\n\n\u003c!-- Added by: alling, at: sön 21 mar 2021 20:35:05 CET --\u003e\n\n\u003c!--te--\u003e\n\n\n# Getting started\n\n## Security notice\n\nMake sure you understand these security aspects before using Userscript Proxy:\n\n  * **You should run the proxy on your own server**, because it can read and modify all traffic sent through it.\n  * **You should not expose the proxy to incoming connections from the Internet**, because then anyone can connect to it and use your Internet connection for whatever they want.\n    In practice, this means that you should _not_ add a port-forward for Userscript Proxy in your router.\n    (Browsing the web via the proxy uses only outgoing connections, which is fine.)\n\n## Starting the proxy\n\n1.  Make sure you have [Docker](https://www.docker.com) installed.\n    This should work:\n\n    ```\n    docker --version\n    ```\n\n1.  Start Userscript Proxy:\n\n    ```\n    docker run -t --rm --name userscript-proxy -p 8080:8080 alling/userscript-proxy\n    ```\n\n    When you see _Proxy server listening at http://*:8080_, the proxy is up and running.\n\n1.  Check that the proxy is working.\n    There are two ways of doing this:\n\n    *   On the command line (in a new terminal):\n\n        ```\n        curl --proxy localhost:8080 http://example.com\n        ```\n\n        The output should contain a `\u003cscript\u003e` element whose first line is `// ==UserScript==`.\n\n    *   In a web browser:\n\n        1.  Go to the preferences menu in your web browser, search for _proxy_ and set `localhost` with port `8080` as HTTP proxy.\n\n        1.  Visit [`http://example.com`](http://example.com).\n            You should see a green page and a message saying that Userscript Proxy is working.\n\n## On a mobile device\n\n1.  You need to know the local IP address of the machine running Userscript Proxy (i.e. where you ran `docker run` above).\n    This is usually something like `192.168.1.67`.\n    You can typically [find it](https://google.com/search?q=find+local+IP+address) by running `ip a`, `ifconfig` or `ipconfig` depending on your operating system.\n\n    If your local IP address is `192.168.1.67`, and the proxy is running (see above), this should work:\n\n    ```\n    curl --proxy 192.168.1.67:8080 http://example.com\n    ```\n\n1.  Your mobile device needs to be on the same LAN as your proxy, so make sure it's connected to your Wi-Fi.\n\n1.  On your mobile device, go to the settings for the currently active Wi-Fi connection.\n    Find the proxy settings, select **Manual proxy** or similar, and set `192.168.1.67` with port `8080`.\n\n1.  Visit [`http://example.com`](http://example.com) on your mobile device.\n    You should see the same green page as above.\n\n## HTTPS\n\nWhen you've set up Userscript Proxy on your mobile device as described above, you'll notice that you can't visit sites via HTTPS anymore.\nThis is because your device thinks you're being [MITM'd](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) (which, technically, you are – by yourself).\n\nTo make HTTPS connections work, you need to tell your device that it should trust your proxy.\nThis is accomplished by installing a certificate.\n\n**In general, installing a certificate might pose a security risk. If you don't trust me and mitmproxy, stop here.**\nOtherwise, read on.\n\n1.  Stop the proxy by pressing `Ctrl` + `C` in the terminal where it's running.\n    Then start it again, this time with the `-v` flag as shown below:\n\n    ```\n    docker run -t --rm --name userscript-proxy -p 8080:8080 -v \"mitmproxy-ca:/root/.mitmproxy\" alling/userscript-proxy\n    ```\n\n    This creates a new Docker volume and mounts it at `/root/.mitmproxy`, where mitmproxy stores its certificate authority files.\n    This is necessary so that you can restart the proxy later without having to perform all these steps again.\n\n    In this example, `mitmproxy-ca` is the name of the new Docker volume.\n    You can choose any name you want, as long as it's not already in use.\n\n1.  Make sure your mobile device is configured to use the proxy as decribed above.\n\n1.  On your mobile device, go to [http://mitm.it](http://mitm.it).\n    You should see icons for Apple, Windows, Android, etc.\n\n1.  Click the icon matching your device.\n\n1.  Install the certificate.\n\n    ### Android\n\n    Follow the on-screen instructions.\n    If you're asked to choose between **VPN and apps** and **Wi-Fi**, choose **VPN and apps**.\n\n    ### iOS\n\n    1.  Tap **Allow** when asked if you want to download a configuration profile.\n\n    1.  Open the Settings app and go to **General** ▶ **Profiles**.\n\n    1.  Under _Downloaded profile_, tap the **mitmproxy** profile.\n\n    1.  Tap **Install** three times.\n\n    1.  Go back to the main screen in Settings and go to **About** ▶ **Certificate Trust Settings**.\n\n    1.  Under _Enable full trust for root certificates_, enable **mitmproxy**, confirming the action if prompted.\n\n1.  You should now be able to browse via HTTPS as usual.\n\n## Deploying userscripts\n\nUserscript Proxy comes with one single userscript, useful only for testing that the proxy is up and running.\nTo use userscripts you've downloaded or written yourself, you need to tell Userscript Proxy where they are.\n\n1.  You need the **absolute path** to a directory containing your userscripts.\n    This could be something like `/home/alling/userscripts`.\n\n1.  Run Userscript Proxy like this:\n\n    ```\n    docker run -t --rm --name userscript-proxy -p 8080:8080 -v \"mitmproxy-ca:/root/.mitmproxy\" -v \"/home/alling/userscripts:/userscripts\" alling/userscript-proxy --userscripts-dir \"/userscripts\"\n    ```\n\n    *   `-v \"/home/alling/userscripts:/userscripts\"` mounts your userscripts directory at `/userscripts` inside the Docker container.\n    *   `--userscripts-dir \"/userscripts\"` tells Userscript Proxy to read userscripts from `/userscripts`.\n\n\n# Apps with certificate pinning\n\nApps like App Store and Facebook Messenger refuse to connect through a MITM proxy, so their traffic must be ignored by mitmproxy.\nThere are two approaches:\n\n  * Blacklisting hosts that cannot connect through the proxy.\n    Tedious, because you have to add exceptions for apps and such all the time.\n  * Whitelisting hosts where userscripts should be applied.\n    Works well in general, but does not allow universal userscripts that run on all sites, and the whitelist must be updated when a new userscript is added.\n\nBlacklisting or whitelisting is done by giving the `--rules` flag together with one or more files containing **rules**.\nBy default, all traffic from hosts matching those rules is ignored (blacklisting); if `--intercept` is given, matching traffic is instead intercepted (whitelisting).\n\n**NOTE:** With `--transparent`, mitmproxy may not be able to see the hostname of responses without intercepting them. In that case, you can only ignore/intercept based on IP address, not hostname.\n\nExamples:\n\n  * Take ignore rules from `/home/alling/rules/ignore.txt`:\n    ```bash\n    docker run -t --rm -v \"/home/alling/rules:/rules\" alling/userscript-proxy --rules \"/rules/ignore.txt\"\n    ```\n  * Take intercept rules from all `.txt` files in the `/home/alling/rules` directory whose names start with `foo`:\n    ```bash\n    docker run -t --rm -v \"/home/alling/rules:/rules\" alling/userscript-proxy --rules \"/rules/foo*.txt\" --intercept\n    ```\n\nRules can be specified in two ways:\n\n## Basic pattern\n\nBased on the syntax used by userscript `@include` directives.\nAsterisk (`*`) means any string (including the empty string).\n`*.` is automatically prepended.\n`:*` is automatically appended unless the rule contains a colon (`:`).\n\nTo match a domain without matching all of its subdomains, use a regex rule instead (see below).\n\n### Examples\n\n| Rule           | Matches                                                         |\n|----------------|-----------------------------------------------------------------|\n| `site.com`     | `site.com` and `x.site.com`                                     |\n| `api.site.com` | `api.site.com` and `x.api.site.com`, but not `www.site.com`     |\n| `*cdn.net`     | `cdn.net`, `fbcdn.net` and `x.fbcdn.net`, but not `cdn.net.com` |\n| `site.com:80`  | `site.com:80` and `x.site.com:80`, but not `site.com:443`       |\n\n## Regular expression\n\nIf a rule starts and ends with a slash (`/`), it is treated as a Python regex.\n\nNote that the string to match against contains both a host and a port, e.g. `example.com:443`, and that the regex is used verbatim (i.e. you have to explicitly provide `^` etc if desired).\nThe only exception is that the case-insensitivity flag (`?i`) is automatically added.\n\nAlso, be careful with `$`: A regex like `/site.com$/` will never match, because it will only be used to check strings like `site.com:80`.\n\nAnything from a `#` until the end of the line is treated as a comment.\nLeading and trailing whitespace have no effect.\n\n### Examples\n\n| Rule            | Matches                                                           |\n|-----------------|-------------------------------------------------------------------|\n| `/cdn\\./`       | `fbcdn.net`, `cdn.site.com`, `cdn.x.site.com`, but not `cdna.com` |\n| `/^site\\.com:/` | `site.com`, but not `x.site.com`, `mysite.com` or `site.com.net`  |\n\n\n# Data usage\n\nUserscript Proxy has no data usage impact when no userscript is injected, i.e. for URLs without any matching userscript.\nWhen a script _is_ injected, **exactly one** of the following things happens:\n\n  * The entire userscript is injected as inline JavaScript (potentially dozens or even hundreds of kilobytes).\n  * A `\u003cscript\u003e` tag referencing the userscript is injected (~100 bytes, depending on the length of the `@downloadURL`).\n\nA userscript is injected by reference if and only if it has a specified `@downloadURL` in its metadata.\n(This can be overridden using the `--inline` flag, in which case all userscripts are injected inline.)\n\nUserscripts are injected into _every_ response from a matching URL, and the size of a userscript can be anything from a few hundred bytes for the most basic ones to hundreds of kilobytes in extreme cases, so there are _massive_ data usage reductions to be gained from making the userscript accessible by URL and including a `@downloadURL`.\nIf the `@downloadURL` approach is not possible, for one reason or the other, it is a good idea to be aware of this issue, and to take appropriate action such as [minifying][minification] userscripts and adding suitable ignore rules.\n\n\n# Userscript compatibility\n\nUserscript Proxy supports (a subset of) the [Greasemonkey metadata syntax][metadata].\nNo adaptation of plain JavaScript userscripts should be required.\nThese directives are supported:\n\n  * `@name`\n  * `@version`\n  * `@run-at document_(start|end|idle)`\n  * `@match`\n  * `@include` (basic pattern and regex)\n  * `@exclude`\n  * `@noframes`\n  * `@downloadURL`\n\nThe [`GM` API][gm-api] and similar runtime facilities are not supported, because userscripts can only be injected as regular scripts.\n\n\n# Options\n\nOptions are specified by simply appending them to the `docker run` command, for example:\n\n```bash\ndocker run -t --rm --name userscript-proxy -p 8080:8080 alling/userscript-proxy --transparent\n#          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                         ^^^^^^^^^^^^^\n#          flags to `docker run`                                                flags to Userscript Proxy\n```\n\n## `--bypass-csp ALLOW`\n\nBypass host site's Content Security Policy (if any) to allow userscripts to run properly.\nIf `ALLOW` is `script`, the CSP is bypassed only for the userscript itself.\nUse `nothing` to never bypass any CSP (meaning userscripts won't work at all on some sites).\nUse `everything` to allow everything, which may be necessary if the userscript injects CSS, images etc.\nNote that the latter completely disables any CSP from every host site into which a userscript is injected.\nDefaults to `script`.\n\n## `--inline`, `-i`\n\nAlways inject scripts inline (`\u003cscript\u003e...\u003c/script\u003e`), never linked (`\u003cscript src=\"...\"\u003e\u003c/script\u003e`).\nUseful to test new userscript features without having to re-upload the userscript and clear browser cache.\n\n## `--list-injected`, `-l`\n\nInsert an HTML comment in each page specifying which userscripts (if any) were injected.\n\n## `--no-default-rules`\n\nSkip built-in default rules, which are otherwise automatically applied so that common apps like App Store and Facebook Messenger work out of the box.\n\n## `--no-default-userscripts`\n\nSkip loading built-in default userscripts intended for sanity checks and similar purposes, e.g. Example Userscript.\n\n## `--port PORT`, `-p PORT`\n\nMake mitmproxy listen to TCP port `PORT`.\nDefaults to `8080`.\n\n**Note:** Be careful when running Userscript Proxy in Docker! If you want to use e.g. port 1337 on the host machine, do this instead:\n\n```bash\ndocker run -t --rm --name userscript-proxy -p 1337:8080 alling/userscript-proxy\n```\n\nIf you really want Userscript Proxy to use a certain port _inside_ the Docker container, e.g. 5555, don't forget to publish that port:\n\n```bash\ndocker run -t --rm --name userscript-proxy -p 1337:5555 alling/userscript-proxy -p 5555\n```\n\nOr you can let the Docker container be a part of the host's network:\n\n```bash\ndocker run -t --rm --network host --name userscript-proxy alling/userscript-proxy -p 5555\n```\n\n## `--query-param-to-disable PARAM`, `-q PARAM`\n\nDisable userscripts when the request URL contains `PARAM` as a query parameter.\nFor example, use `-q foo` to disable userscripts for `http://example.com?foo`.\nDefaults to `nouserscripts`.\n\n## `--rules FILE`\n\nTake ignore or intercept rules from `FILE`, which can be a glob pattern matching multiple files.\nBy default, matching traffic is ignored; use `--intercept` to invert this behavior.\nSee examples above.\n\n## `--transparent`, `-t`\n\nRun mitmproxy in [transparent mode][transparent-mode].\nUseful if you cannot set a proxy in the client, e.g. when using OpenVPN Connect on Android to connect to a VPN server on the network where your proxy is running.\nIn such cases, you have to route traffic from the client to the proxy at the network layer instead, making transparent mode necessary.\n\n**NOTE:** In transparent mode, ignore/intercept rules based on hostname (rather than IP address) may not work, because mitmproxy may not be able to see the hostname of responses without intercepting them.\n\n## `--userscripts-dir DIR`, `-u DIR`\n\nLoad userscripts from directory `DIR`.\n\n\n# Contribute\n\nHow to build and run from source:\n\n```\ngit clone https://github.com/SimonAlling/userscript-proxy\ncd userscript-proxy\nmake start\n```\n\n\n[mitmproxy]: https://mitmproxy.org\n[minification]: https://en.wikipedia.org/wiki/Minification_(programming)\n[metadata]: https://wiki.greasespot.net/Metadata_Block\n[transparent-mode]: https://docs.mitmproxy.org/stable/concepts-modes/#transparent-proxy\n[gm-api]: https://wiki.greasespot.net/GM.getValue\n","funding_links":["https://ko-fi.com/alling"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonalling%2Fuserscript-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonalling%2Fuserscript-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonalling%2Fuserscript-proxy/lists"}