swat-proxy acts as a man-in-the-middle between browser and server, altering the server response for specified pages. The browser renders the modified response as if it came directly from the server itself. This allows viewing and interacting with content on the target page.
The name swat-proxy derives from the name of the Small Web-Apps Technology team whose members built the first iteration of this tool.
npm install swat-proxy
Write a script that runs the Proxy
/* Filename: do-proxy.js */// Import swat-proxy.var swat_proxy = ;// Add some JS to the end of the Google homepage.swat_proxy;// Start the proxy server.swat_proxystart;
Run your Script
By default swat-proxy runs on port
8063 so set your browser to use the proxy
127.0.0.1:8063 and navigate to
You should be immediately presented with the greeting alert, and you can
body tag (
Let us dig a little deeper.
A call to
.proxy is referred to as a proxy block:
The way to read this proxy block is:
contentto the body of
Removing Proxy Blocks
In order to prevent memory leaks over the lifetime of potentially long-running
proxy scripts, when new proxy URLs may be registered in an ad hoc fashion, a
.removeProxy function is also provided. An example usage might look like this:
var options =selector: 'body'manipulation: swat_proxyManipulationsAPPENDcontent: '<script> alert ("Hello from swat-proxy!"); </script>';swat_proxy;swat_proxy;// ORswat_proxy;
Note that any options objects passed to
.removeProxy are compared by reference,
not by value. If you want to remove an options object from your proxy at a future
time, you need to store a reference for it in a variable, to be passed later. If
you simply want to clear all proxies associated with a given URL, you can ignore
the second option and just pass the target URL.
Let us break down the parameters of proxy blocks. The most up-to-date documentation can always be found in the source code, but for convenience it is detailed here as well. Refer to the following signature:
The target URL to inject content into. Example
Note that this must match exactly to the browser URL -
www.google.com. In other words, if you point your proxy block at
google.com but navigate to
www.google.com, your content will not be injected.
The easiest way to grab your target URL is to navigate to your target page and
copy/paste the URL directly into your proxy block code. For example, typing
google.com into Firefox and copy/pasting results in
is the value you want to use.
A CSS selector to target DOM elements. Examples
swat-proxy provides an enumeration of supported DOM manipulations to be used
as values for
manipulation. They are:
contentas the last child of each of the selected elements.
contentas the first child of each of the selected elements.
REPLACE: Replace selected elements with
WRAP: Wrap selected elements with
swat-proxy uses the
cheerio package under the hood. For more information on
these manipulations, see the cheerio documentation.
A string containing the content to inject, or a function that returns a string of content to be injected. If passing a function, it will receive the original element's markup for transformation, and is expected to return the transformed markup. Since content is injected into an HTML page, it is important to wrap the content with the appropriate HTML tags.
swat-proxy also provides an enumeration of matchType algorithms for some flexibility
in the way it matches URLs. For backwards compatibility, this field is optional, and
EXACT. The values in the matchType enumeration are:
DOMAIN: Match against just the domain portion of the url. This includes subdomain.
EXACT: Match the url exactly as it's been entered, including query parameters.
PREFIX: Match the target URL against the beginning of the requested URL (i.e. URL starts with)
matchType option is provided as part of the options object(s) passed to the
function, meaning you can provide a different
matchType parameter for each rule in the
overall set of options, if you desire different behavior based on the URL stub.
React is currently very popular for building front-end user interfaces.
Here is an example of using React to generate markup to assign to
/* Filename: MyWidget.js */moduleexports = React;
/* Filename: main.js */var MyWidget = ;const WidgetFactory = React;const widgetContent = ReactDOMServer;swat_proxy;
Third Party JS Common Use Case
customers to place on their page (a) a container
<div> where content should
appear, and (b) a
<script> tag to load the application that will place content
into the container element.
This can be simulated by injecting more than one piece of content into a page
Using an Array
Pass an array of manipulation instructions into a single proxy block, like so:
Multiple Proxy Blocks
The same result can be achieved using multiple proxy blocks with the same target URL:
Q: Why is my content not injected?
.start function supports a
debugMode property that can hopefully
// Start the proxy server in debug mode.swat_proxystart debugMode: true ;
This will log each request URL from to the console and notify when that URL matches the URL of any proxy block. If there are no matches, revisit the proxy block's url configuration.
Q: I keep getting
Error: listen EADDRINUSE :::8063?
A: The target port (
8063) is currently in use, most likely because another
instance of the proxy server is running. Shut down that process and try again.
If another service is using that port, it is possible to instruct
to use a different port:
// Start the proxy server on port 8064.swat_proxystart port: 8064 ;
Q: My injection worked yesterday and today it doesn't - I haven't changed anything! A: Many third parties change their web pages on a frequent basis. Ensure that the selectors used in code and configuration still exist.
Please refer to the Contributing Guidelines.