diff --git a/js/customElements/image.js b/js/customElements/image.js
new file mode 100644
index 0000000000000000000000000000000000000000..2fb626c779da5d34858630337ea1aa9f9560dd0f
--- /dev/null
+++ b/js/customElements/image.js
@@ -0,0 +1,34 @@
+class CustomImage extends HTMLElement {
+    async connectedCallback(){
+        const originalURL = new URL(this.getAttribute("src"), document.baseURI).href;
+
+
+        var graphql = JSON.stringify({
+            query: "query($url: String) {imgproxy(url: $url)}",
+            variables: {
+                "url": originalURL
+            }
+        })
+        var requestOptions = {
+            method: 'POST',
+            body: graphql,
+            headers: { 'Content-Type': 'application/json' }
+        };
+
+        let imgproxy = (await (await fetch("/API/graphql.php", requestOptions)).json()).data.imgproxy;
+        
+        let image = document.createElement("img");
+        image.src = imgproxy;
+        image.setAttribute("alt", this.getAttribute("alt"));
+        image.setAttribute("title", this.getAttribute("title"));
+        image.setAttribute("class", this.getAttribute("class"));
+        image.setAttribute("style", this.getAttribute("style"));
+        image.setAttribute("width", this.getAttribute("width"));
+        image.setAttribute("height", this.getAttribute("height"));
+        image.setAttribute("loading", "lazy");
+        image.setAttribute("original-src", originalURL);
+        this.appendChild(image);
+    }
+}
+
+customElements.define("jl-img", CustomImage)
\ No newline at end of file
diff --git a/js/script.js b/js/script.js
index 5f6c38dd737cb85d80e03239743e3518b794b798..32c54c26114c45829238d7f75dddeaffdfe68ff6 100644
--- a/js/script.js
+++ b/js/script.js
@@ -20,3 +20,4 @@ require("./customElements/skills");
 require("./customElements/pwgen");
 require("./customElements/inline-code");
 require("./customElements/404Buttons");
+require("./customElements/image");
\ No newline at end of file
diff --git a/public/API/queries/imgproxy.php b/public/API/queries/imgproxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..61e6ee8d1f3fabdb24034cd3aa9cb52a7df18aba
--- /dev/null
+++ b/public/API/queries/imgproxy.php
@@ -0,0 +1,10 @@
+<?php
+
+function imgproxy($imageURL) {
+        require "./lib/config.php";
+        $encodedUrl = rtrim(strtr(base64_encode($imageURL), '+/', '-_'), '=');
+        $path = "/rs:fit:0:120:1/g:no/{$encodedUrl}.webp";
+
+        $signature = rtrim(strtr(base64_encode(hash_hmac('sha256', $imgProxySalt.$path, $imgProxyKey, true)), '+/', '-_'), '=');
+        return $imgProxyUrl . "/" . $signature . $path;
+}
diff --git a/public/API/queries/queries.php b/public/API/queries/queries.php
index 962ee874eff5418477ba3c09605fc711e555d5b3..091d6b621f09dbf738cd895547df754508e85b8a 100644
--- a/public/API/queries/queries.php
+++ b/public/API/queries/queries.php
@@ -7,6 +7,7 @@ require "./queries/blogPost.php";
 require "./queries/comments.php";
 require "./queries/mailAddress.php";
 require "./queries/ebayKleinanzeigen.php";
+require "./queries/imgproxy.php";
 
 
 $queryType = new ObjectType([
@@ -62,6 +63,13 @@ $queryType = new ObjectType([
                 ]
             ],
             'resolve' => fn ($rootValue, $args) => ebayKleinanzeigen($args["imageCount"]),
+        ],
+        'imgproxy' => [
+            "type" => Type::string(),
+            "args" => [
+                "url" => Type::nonNull(Type::string()),
+            ],
+            'resolve' => fn ($rootValue, $args) => imgproxy($args["url"]),
         ]
 
     ]