Modify HTTP responses from a Chrome extension

In general, you cannot change the response body of a HTTP request using the standard Chrome extension APIs.

This feature is being requested at 104058: WebRequest API: allow extension to edit response body. Star the issue to get notified of updates.

If you want to edit the response body for a known XMLHttpRequest, inject code via a content script to override the default XMLHttpRequest constructor with a custom (full-featured) one that rewrites the response before triggering the real event. Make sure that your XMLHttpRequest object is fully compliant with Chrome's built-in XMLHttpRequest object, or AJAX-heavy sites will break.

In other cases, you can use the chrome.webRequest or chrome.declarativeWebRequest APIs to redirect the request to a data:-URI. Unlike the XHR-approach, you won't get the original contents of the request. Actually, the request will never hit the server because redirection can only be done before the actual request is sent. And if you redirect a main_frame request, the user will see the data:-URI instead of the requested URL.


I just released a Devtools extension that does just that :)

It's called tamper, it's based on mitmproxy and it allows you to see all requests made by the current tab, modify them and serve the modified version next time you refresh.

It's a pretty early version but it should be compatible with OS X and Windows. Let me know if it doesn't work for you.

You can get it here http://dutzi.github.io/tamper/

How this works

As @Xan commented below, the extension communicates through Native Messaging with a python script that extends mitmproxy.

The extension lists all requests using chrome.devtools.network.onRequestFinished.

When you click on of the requests it downloads its response using the request object's getContent() method, and then sends that response to the python script which saves it locally.

It then opens file in an editor (using call for OSX or subprocess.Popen for windows).

The python script uses mitmproxy to listen to all communication made through that proxy, if it detects a request for a file that was saved it serves the file that was saved instead.

I used Chrome's proxy API (specifically chrome.proxy.settings.set()) to set a PAC as the proxy setting. That PAC file redirect all communication to the python script's proxy.

One of the greatest things about mitmproxy is that it can also modify HTTPs communication. So you have that also :)