diff --git a/surf.c b/surf.c
index 93a1629..ba53b94 100644
--- a/surf.c
+++ b/surf.c
@@ -217,6 +217,7 @@ static void togglefullscreen(Client *c, const Arg *a);
 static void togglecookiepolicy(Client *c, const Arg *a);
 static void toggleinspector(Client *c, const Arg *a);
 static void find(Client *c, const Arg *a);
+static void externalpipe(Client *c, const Arg *a);
 
 /* Buttons */
 static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h);
@@ -241,6 +242,80 @@ char *argv0;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
+static void
+externalpipe_execute(char* buffer, Arg *arg) {
+	int to[2];
+	void (*oldsigpipe)(int);
+
+	if (pipe(to) == -1)
+		return;
+
+	switch (fork()) {
+	case -1:
+		close(to[0]);
+		close(to[1]);
+		return;
+	case 0:
+		dup2(to[0], STDIN_FILENO); close(to[0]); close(to[1]);
+		execvp(((char **)arg->v)[0], (char **)arg->v);
+		fprintf(stderr, "st: execvp %s\n", ((char **)arg->v)[0]);
+		perror("failed");
+		exit(0);
+	}
+
+	close(to[0]);
+	oldsigpipe = signal(SIGPIPE, SIG_IGN);
+	write(to[1], buffer, strlen(buffer));
+	close(to[1]);
+	signal(SIGPIPE, oldsigpipe);
+}
+
+static void
+externalpipe_resource_done(WebKitWebResource *r, GAsyncResult *s, Arg *arg)
+{
+	GError *gerr = NULL;
+	guchar *buffer = webkit_web_resource_get_data_finish(r, s, NULL, &gerr);
+	if (gerr == NULL) {
+		externalpipe_execute((char *) buffer, arg);
+	} else {
+		g_error_free(gerr);
+	}
+	g_free(buffer);
+}
+
+static void
+externalpipe_js_done(WebKitWebView *wv, GAsyncResult *s, Arg *arg)
+{
+	WebKitJavascriptResult *j = webkit_web_view_run_javascript_finish(
+		wv, s, NULL);
+	if (!j) {
+		return;
+	}
+	JSCValue *v = webkit_javascript_result_get_js_value(j);
+	if (jsc_value_is_string(v)) {
+		char *buffer = jsc_value_to_string(v);
+		externalpipe_execute(buffer, arg);
+		g_free(buffer);
+	}
+	webkit_javascript_result_unref(j);
+}
+
+void
+externalpipe(Client *c, const Arg *arg)
+{
+	if (curconfig[JavaScript].val.i) {
+		webkit_web_view_run_javascript(
+			c->view, "window.document.documentElement.outerHTML",
+			NULL, externalpipe_js_done, arg);
+	} else {
+		WebKitWebResource *resource = webkit_web_view_get_main_resource(c->view);
+		if (resource != NULL) {
+			webkit_web_resource_get_data(
+				resource, NULL, externalpipe_resource_done, arg);
+		}
+	}
+}
+
 void
 usage(void)
 {
