diff --git a/ext/image/image_test.go b/ext/image/image_test.go
new file mode 100644
index 00000000..620f5cfa
--- /dev/null
+++ b/ext/image/image_test.go
@@ -0,0 +1,171 @@
+package goproxy_image_test
+
+import (
+	"bytes"
+	"crypto/tls"
+	"github.com/elazarl/goproxy"
+	goproxy_image "github.com/elazarl/goproxy/ext/image"
+	"image"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"testing"
+)
+
+var acceptAllCerts = &tls.Config{InsecureSkipVerify: true}
+
+func oneShotProxy(proxy *goproxy.ProxyHttpServer, t *testing.T) (client *http.Client, s *httptest.Server) {
+	s = httptest.NewServer(proxy)
+
+	proxyUrl, _ := url.Parse(s.URL)
+	tr := &http.Transport{TLSClientConfig: acceptAllCerts, Proxy: http.ProxyURL(proxyUrl)}
+	client = &http.Client{Transport: tr}
+	return
+}
+
+func getImage(file string, t *testing.T) image.Image {
+	newimage, err := os.ReadFile(file)
+	if err != nil {
+		t.Fatal("Cannot read file", file, err)
+	}
+	img, _, err := image.Decode(bytes.NewReader(newimage))
+	if err != nil {
+		t.Fatal("Cannot decode image", file, err)
+	}
+	return img
+}
+
+func compareImage(eImg, aImg image.Image, t *testing.T) {
+	if eImg.Bounds().Dx() != aImg.Bounds().Dx() || eImg.Bounds().Dy() != aImg.Bounds().Dy() {
+		t.Error("image sizes different")
+		return
+	}
+	for i := 0; i < eImg.Bounds().Dx(); i++ {
+		for j := 0; j < eImg.Bounds().Dy(); j++ {
+			er, eg, eb, ea := eImg.At(i, j).RGBA()
+			ar, ag, ab, aa := aImg.At(i, j).RGBA()
+			if er != ar || eg != ag || eb != ab || ea != aa {
+				t.Error("images different at", i, j, "vals\n", er, eg, eb, ea, "\n", ar, ag, ab, aa, aa)
+				return
+			}
+		}
+	}
+}
+
+var fs = httptest.NewServer(http.FileServer(http.Dir(".")))
+
+func localFile(url string) string { return fs.URL + "/" + url }
+
+func TestConstantImageHandler(t *testing.T) {
+	proxy := goproxy.NewProxyHttpServer()
+	football := getImage("test_data/football.png", t)
+	proxy.OnResponse().Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
+		return football
+	}))
+
+	client, l := oneShotProxy(proxy, t)
+	defer l.Close()
+
+	resp, err := client.Get(localFile("test_data/panda.png"))
+	if err != nil {
+		t.Fatal("Cannot get panda.png", err)
+	}
+
+	img, _, err := image.Decode(resp.Body)
+	if err != nil {
+		t.Error("decode", err)
+	} else {
+		compareImage(football, img, t)
+	}
+}
+
+func TestImageHandler(t *testing.T) {
+	proxy := goproxy.NewProxyHttpServer()
+	football := getImage("test_data/football.png", t)
+
+	proxy.OnResponse(goproxy.UrlIs("/test_data/panda.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
+		return football
+	}))
+
+	client, l := oneShotProxy(proxy, t)
+	defer l.Close()
+
+	resp, err := client.Get(localFile("test_data/panda.png"))
+	if err != nil {
+		t.Fatal("Cannot get panda.png", err)
+	}
+
+	img, _, err := image.Decode(resp.Body)
+	if err != nil {
+		t.Error("decode", err)
+	} else {
+		compareImage(football, img, t)
+	}
+
+	// and again
+	resp, err = client.Get(localFile("test_data/panda.png"))
+	if err != nil {
+		t.Fatal("Cannot get panda.png", err)
+	}
+
+	img, _, err = image.Decode(resp.Body)
+	if err != nil {
+		t.Error("decode", err)
+	} else {
+		compareImage(football, img, t)
+	}
+}
+
+func fatalOnErr(err error, msg string, t *testing.T) {
+	if err != nil {
+		t.Fatal(msg, err)
+	}
+}
+
+func get(url string, client *http.Client) ([]byte, error) {
+	resp, err := client.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	txt, err := io.ReadAll(resp.Body)
+	defer resp.Body.Close()
+	if err != nil {
+		return nil, err
+	}
+	return txt, nil
+}
+
+func getOrFail(url string, client *http.Client, t *testing.T) []byte {
+	txt, err := get(url, client)
+	if err != nil {
+		t.Fatal("Can't fetch url", url, err)
+	}
+	return txt
+}
+
+func TestReplaceImage(t *testing.T) {
+	proxy := goproxy.NewProxyHttpServer()
+
+	panda := getImage("test_data/panda.png", t)
+	football := getImage("test_data/football.png", t)
+
+	proxy.OnResponse(goproxy.UrlIs("/test_data/panda.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
+		return football
+	}))
+	proxy.OnResponse(goproxy.UrlIs("/test_data/football.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
+		return panda
+	}))
+
+	client, l := oneShotProxy(proxy, t)
+	defer l.Close()
+
+	imgByPandaReq, _, err := image.Decode(bytes.NewReader(getOrFail(localFile("test_data/panda.png"), client, t)))
+	fatalOnErr(err, "decode panda", t)
+	compareImage(football, imgByPandaReq, t)
+
+	imgByFootballReq, _, err := image.Decode(bytes.NewReader(getOrFail(localFile("test_data/football.png"), client, t)))
+	fatalOnErr(err, "decode football", t)
+	compareImage(panda, imgByFootballReq, t)
+}
diff --git a/go.mod b/go.mod
index 278a4f92..8ef6b038 100644
--- a/go.mod
+++ b/go.mod
@@ -2,9 +2,6 @@ module github.com/elazarl/goproxy
 
 go 1.20
 
-require (
-	github.com/elazarl/goproxy/ext v0.0.0-20241217120900-7711dfa3811c
-	golang.org/x/net v0.33.0
-)
+require golang.org/x/net v0.33.0
 
 require golang.org/x/text v0.21.0 // indirect
diff --git a/go.sum b/go.sum
index 2a9d0c08..845330e7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,3 @@
-github.com/elazarl/goproxy/ext v0.0.0-20241217120900-7711dfa3811c h1:R+i10jtNSzKJKqEZAYJnR9M8y14k0zrNHqD1xkv/A2M=
-github.com/elazarl/goproxy/ext v0.0.0-20241217120900-7711dfa3811c/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
-github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
-golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
-golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
 golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
 golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
diff --git a/proxy_test.go b/proxy_test.go
index 426339d3..6d164e81 100644
--- a/proxy_test.go
+++ b/proxy_test.go
@@ -8,7 +8,6 @@ import (
 	"crypto/x509"
 	"encoding/base64"
 	"fmt"
-	"image"
 	"io"
 	"net"
 	"net/http"
@@ -22,7 +21,6 @@ import (
 	"time"
 
 	"github.com/elazarl/goproxy"
-	goproxy_image "github.com/elazarl/goproxy/ext/image"
 )
 
 var acceptAllCerts = &tls.Config{InsecureSkipVerify: true}
@@ -221,18 +219,6 @@ func TestContentType(t *testing.T) {
 	}
 }
 
-func getImage(file string, t *testing.T) image.Image {
-	newimage, err := os.ReadFile(file)
-	if err != nil {
-		t.Fatal("Cannot read file", file, err)
-	}
-	img, _, err := image.Decode(bytes.NewReader(newimage))
-	if err != nil {
-		t.Fatal("Cannot decode image", file, err)
-	}
-	return img
-}
-
 func readAll(r io.Reader, t *testing.T) []byte {
 	b, err := io.ReadAll(r)
 	if err != nil {
@@ -259,84 +245,6 @@ func panicOnErr(err error, msg string) {
 	}
 }
 
-func compareImage(eImg, aImg image.Image, t *testing.T) {
-	if eImg.Bounds().Dx() != aImg.Bounds().Dx() || eImg.Bounds().Dy() != aImg.Bounds().Dy() {
-		t.Error("image sizes different")
-		return
-	}
-	for i := 0; i < eImg.Bounds().Dx(); i++ {
-		for j := 0; j < eImg.Bounds().Dy(); j++ {
-			er, eg, eb, ea := eImg.At(i, j).RGBA()
-			ar, ag, ab, aa := aImg.At(i, j).RGBA()
-			if er != ar || eg != ag || eb != ab || ea != aa {
-				t.Error("images different at", i, j, "vals\n", er, eg, eb, ea, "\n", ar, ag, ab, aa, aa)
-				return
-			}
-		}
-	}
-}
-
-func TestConstantImageHandler(t *testing.T) {
-	proxy := goproxy.NewProxyHttpServer()
-	//panda := getImage("panda.png", t)
-	football := getImage("test_data/football.png", t)
-	proxy.OnResponse().Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
-		return football
-	}))
-
-	client, l := oneShotProxy(proxy, t)
-	defer l.Close()
-
-	resp, err := client.Get(localFile("test_data/panda.png"))
-	if err != nil {
-		t.Fatal("Cannot get panda.png", err)
-	}
-
-	img, _, err := image.Decode(resp.Body)
-	if err != nil {
-		t.Error("decode", err)
-	} else {
-		compareImage(football, img, t)
-	}
-}
-
-func TestImageHandler(t *testing.T) {
-	proxy := goproxy.NewProxyHttpServer()
-	football := getImage("test_data/football.png", t)
-
-	proxy.OnResponse(goproxy.UrlIs("/test_data/panda.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
-		return football
-	}))
-
-	client, l := oneShotProxy(proxy, t)
-	defer l.Close()
-
-	resp, err := client.Get(localFile("test_data/panda.png"))
-	if err != nil {
-		t.Fatal("Cannot get panda.png", err)
-	}
-
-	img, _, err := image.Decode(resp.Body)
-	if err != nil {
-		t.Error("decode", err)
-	} else {
-		compareImage(football, img, t)
-	}
-
-	// and again
-	resp, err = client.Get(localFile("test_data/panda.png"))
-	if err != nil {
-		t.Fatal("Cannot get panda.png", err)
-	}
-
-	img, _, err = image.Decode(resp.Body)
-	if err != nil {
-		t.Error("decode", err)
-	} else {
-		compareImage(football, img, t)
-	}
-}
-
 func TestChangeResp(t *testing.T) {
 	proxy := goproxy.NewProxyHttpServer()
 	proxy.OnResponse().DoFunc(func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
@@ -358,30 +266,6 @@ func TestChangeResp(t *testing.T) {
 		t.Fatal(err)
 	}
 }
-func TestReplaceImage(t *testing.T) {
-	proxy := goproxy.NewProxyHttpServer()
-
-	panda := getImage("test_data/panda.png", t)
-	football := getImage("test_data/football.png", t)
-
-	proxy.OnResponse(goproxy.UrlIs("/test_data/panda.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
-		return football
-	}))
-	proxy.OnResponse(goproxy.UrlIs("/test_data/football.png")).Do(goproxy_image.HandleImage(func(img image.Image, ctx *goproxy.ProxyCtx) image.Image {
-		return panda
-	}))
-
-	client, l := oneShotProxy(proxy, t)
-	defer l.Close()
-
-	imgByPandaReq, _, err := image.Decode(bytes.NewReader(getOrFail(localFile("test_data/panda.png"), client, t)))
-	fatalOnErr(err, "decode panda", t)
-	compareImage(football, imgByPandaReq, t)
-
-	imgByFootballReq, _, err := image.Decode(bytes.NewReader(getOrFail(localFile("test_data/football.png"), client, t)))
-	fatalOnErr(err, "decode football", t)
-	compareImage(panda, imgByFootballReq, t)
-}
 
 func getCert(c *tls.Conn, t *testing.T) []byte {
 	if err := c.Handshake(); err != nil {