diff --git a/app/Http/Controllers/HumanVerification.php b/app/Http/Controllers/HumanVerification.php
index 0ff75e435ab6dd57adb1c3abbe60e926b109f429..6f546231408d1545732dac20c573e74b9ab5c0c6 100644
--- a/app/Http/Controllers/HumanVerification.php
+++ b/app/Http/Controllers/HumanVerification.php
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use Captcha;
 use Carbon;
+use Cookie;
 use Illuminate\Hashing\BcryptHasher as Hasher;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Cache;
@@ -270,4 +271,84 @@ class HumanVerification extends Controller
         HumanVerification::saveUser($user);
         return redirect('admin/bot');
     }
+
+    public function browserVerification(Request $request)
+    {
+        $key = $request->input("id", "");
+
+        // Verify that key is a md5 checksum
+        if (!preg_match("/^[a-f0-9]{32}$/", $key)) {
+            abort(404);
+        }
+
+        Redis::connection("cache")->pipeline(function ($redis) use ($key) {
+            $redis->rpush($key, true);
+            $redis->expire($key, 30);
+        });
+
+        return response("", 200)->header("Content-Type", "text/css");
+    }
+
+    public static function block(Request $request)
+    {
+        $prefix = "humanverification";
+
+        $ip = $request->ip();
+        $id = "";
+        $uid = "";
+        if (\App\Http\Controllers\HumanVerification::couldBeSpammer($ip)) {
+            $id = hash("sha1", "999.999.999.999");
+            $uid = hash("sha1", "999.999.999.999" . $ip . $_SERVER["AGENT"] . "uid");
+        } else {
+            $id = hash("sha1", $ip);
+            $uid = hash("sha1", $ip . $_SERVER["AGENT"] . "uid");
+        }
+
+        /**
+         * If the user sends a Password or a key
+         * We will not verificate the user.
+         * If someone that uses a bot finds this out we
+         * might have to change it at some point.
+         */
+        if ($request->filled('password') || $request->filled('key') || Cookie::get('key') !== null || $request->filled('appversion') || !env('BOT_PROTECTION', false)) {
+            $update = false;
+            return $next($request);
+        }
+
+        # Get all Users of this IP
+        $users = Cache::get($prefix . "." . $id, []);
+
+        $user = [];
+        $changed = false;
+        if (empty($users[$uid])) {
+            $user = [
+                'uid' => $uid,
+                'id' => $id,
+                'unusedResultPages' => 0,
+                'whitelist' => false,
+                'locked' => true,
+                "lockedKey" => "",
+                "expiration" => now()->addWeeks(2),
+            ];
+            $changed = true;
+        } else {
+            $user = $users[$uid];
+            if (!$user["locked"]) {
+                $user["locked"] = true;
+                $changed = true;
+            }
+        }
+
+        if ($user["whitelist"]) {
+            $user["expiration"] = now()->addWeeks(2);
+        } else {
+            $user["expiration"] = now()->addHours(72);
+        }
+        if ($changed) {
+            $userList = Cache::get($prefix . "." . $user["id"], []);
+            $userList[$user["uid"]] = $user;
+            Cache::put($prefix . "." . $user["id"], $userList, 2 * 7 * 24 * 60 * 60);
+        }
+        return [$id, $uid];
+    }
 }
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 24a8c577ad62a61ca1483aa960a79c646daf5593..cb14ae7025a3077233dfb5cd09cd401242a20a52 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -62,5 +62,6 @@ class Kernel extends HttpKernel
         'referer.check' => \App\Http\Middleware\RefererCheck::class,
         'humanverification' => \App\Http\Middleware\HumanVerification::class,
         'useragentmaster' => \App\Http\Middleware\UserAgentMaster::class,
+        'browserverification' => \App\Http\Middleware\BrowserVerification::class,
     ];
 }
diff --git a/app/Http/Middleware/BrowserVerification.php b/app/Http/Middleware/BrowserVerification.php
new file mode 100644
index 0000000000000000000000000000000000000000..463fff13b095ce295f6201f14bd789d708286e9e
--- /dev/null
+++ b/app/Http/Middleware/BrowserVerification.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use GrahamCampbell\Throttle\Facades\Throttle;
+use Illuminate\Support\Facades\Redis;
+use \App\Http\Controllers\HumanVerification;
+
+class BrowserVerification
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        $bvEnabled = config("metager.metager.browserverification_enabled");
+        if (empty($bwEnabled) || !$bvEnabled) {
+            return $next($request);
+        }
+
+        // Check if throttled
+        $accept = Throttle::check($request, 8, 1);
+        if (!$accept) {
+            Throttle::hit($request, 8, 1);
+            abort(429);
+        }
+        header('Content-type: text/html; charset=utf-8');
+        header('X-Accel-Buffering: no');
+        ini_set('zlib.output_compression', 'Off');
+        ini_set('output_buffering', 'Off');
+        ini_set('output_handler', '');
+
+        ob_end_clean();
+
+        $key = md5($request->ip() . microtime(true));
+
+        echo (view('layouts.resultpage.verificationHeader')->with('key', $key)->render());
+        flush();
+
+        $answer = boolval(Redis::connection("cache")->blpop($key, 5));
+
+        if ($answer === true) {
+            return $next($request);
+        } else {
+            $accept = Throttle::attempt($request, 8, 1);
+            if (!$accept) {
+                abort(429);
+            }
+
+            # Lockout
+            $ids = HumanVerification::block($request);
+        }
+
+        return redirect()->route('captcha', ["id" => $ids[0], "uid" => $ids[1], "url" => url()->full()]);
+
+    }
+}
diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml
index 25bf29e5e87ae243868f6199f8477b10c6f308db..62ff4b8d2cd2c8626cd11871b0802a4b9237a23a 100644
--- a/chart/templates/deployment.yaml
+++ b/chart/templates/deployment.yaml
@@ -63,6 +63,9 @@ spec:
       - name: blacklist-ad
         secret:
           secretName: metager-ad-blacklist
+      - name: metager-config
+        configMap:
+          name: metager
       containers:
       - name: {{ .Chart.Name }}-phpfpm
         image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
@@ -93,6 +96,9 @@ spec:
           initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
           timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
         volumeMounts:
+        - name: metager-config
+          mountPath: /html/config
+          readOnly: true
         - name: mglogs-persistent-storage
           mountPath: /html/storage/logs/metager
           readOnly: false
diff --git a/composer.json b/composer.json
index 1bc55bcf84f89cef661abeeb276151310059c14f..51824d44b9bda46b3b7046978aa43678d97808d0 100644
--- a/composer.json
+++ b/composer.json
@@ -8,17 +8,18 @@
     ],
     "license": "MIT",
     "require": {
-        "laravel/framework": "5.8.*",
         "php": "^7.1.3",
+        "endclothing/prometheus_client_php": "^1.0",
         "fideloper/proxy": "^4.0",
-        "laravel/tinker": "^1.0",
         "globalcitizen/php-iban": "^2.6",
+        "graham-campbell/throttle": "^7.5",
         "jenssegers/agent": "^2.6",
+        "laravel/framework": "5.8.*",
+        "laravel/tinker": "^1.0",
         "mcamara/laravel-localization": "dev-master#13f418e481ed06f482e4fca87ec5ff67c2949373",
         "mews/captcha": "^2.2",
         "predis/predis": "^1.1",
-        "symfony/dom-crawler": "^4.1",
-        "endclothing/prometheus_client_php": "^1.0"
+        "symfony/dom-crawler": "^4.1"
     },
     "require-dev": {
         "beyondcode/laravel-dump-server": "^1.0",
@@ -69,4 +70,4 @@
             "@php artisan key:generate --ansi"
         ]
     }
-}
\ No newline at end of file
+}
diff --git a/config/metager/metager.php b/config/metager/metager.php
new file mode 100644
index 0000000000000000000000000000000000000000..cb7825e6ff35e166caaad4bb108e456ae9960652
--- /dev/null
+++ b/config/metager/metager.php
@@ -0,0 +1,5 @@
+<?php
+
+return [
+    "browserverification_enabled" => true,
+];
diff --git a/resources/lang/de/429.php b/resources/lang/de/429.php
new file mode 100644
index 0000000000000000000000000000000000000000..60911729971a159d9d5853a63ba9a28b4aaf49ee
--- /dev/null
+++ b/resources/lang/de/429.php
@@ -0,0 +1,6 @@
+<?php
+
+return [
+    'title' => '429 - Zu viele Anfragen',
+    'text' => '',
+];
diff --git a/resources/lang/en/429.php b/resources/lang/en/429.php
new file mode 100644
index 0000000000000000000000000000000000000000..ccc7579bf259d84c33ab5efc69d11978529a0a7d
--- /dev/null
+++ b/resources/lang/en/429.php
@@ -0,0 +1,6 @@
+<?php
+
+return [
+    'title' => '429 - Too many Requests',
+    'text' => '',
+];
diff --git a/resources/views/errors/404.blade.php b/resources/views/errors/404.blade.php
index f4f87a3057bccc53b632151c4679f545cbdab650..0f928a9db9a03e120b1787b72b5b93c3ff09f5be 100644
--- a/resources/views/errors/404.blade.php
+++ b/resources/views/errors/404.blade.php
@@ -3,6 +3,12 @@
 @section('title', 'Fehler 404 - Seite nicht gefunden')
 
 @section('content')
+	<style>
+		main#main-content {
+			align-items: center;
+			justify-content: center;
+		}
+	</style>
 	<h1>{{ trans('404.title') }}</h1>
 	<p>{{ trans('404.text') }}</p>
 @endsection
diff --git a/resources/views/errors/429.blade.php b/resources/views/errors/429.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..4592b922a7e228614cd567fbd511d165be4fd9f7
--- /dev/null
+++ b/resources/views/errors/429.blade.php
@@ -0,0 +1,14 @@
+@extends('layouts.subPages')
+
+@section('title', trans('429.title'))
+
+@section('content')
+	<style>
+		main#main-content {
+			align-items: center;
+			justify-content: center;
+		}
+	</style>
+	<h1>{{ trans('429.title') }}</h1>
+	<p>{{ trans('429.text') }}</p>
+@endsection
diff --git a/resources/views/layouts/resultpage/verificationHeader.blade.php b/resources/views/layouts/resultpage/verificationHeader.blade.php
new file mode 100644
index 0000000000000000000000000000000000000000..58e20f52f293f1aff832677524db625684233fb1
--- /dev/null
+++ b/resources/views/layouts/resultpage/verificationHeader.blade.php
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <link rel="stylesheet" href="/index.css?id={{ $key }}">
diff --git a/routes/web.php b/routes/web.php
index ce435e61790ff2b67a50b7e74afbb6b17abd8603..ede8a3b07ed480aba19b92a5734143280224b0c1 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -195,13 +195,14 @@ Route::group(
             return redirect(LaravelLocalization::getLocalizedURL(LaravelLocalization::getCurrentLocale(), '/'));
         });
 
-        Route::match(['get', 'post'], 'meta/meta.ger3', 'MetaGerSearch@search')->middleware('humanverification', 'useragentmaster');
+        Route::match(['get', 'post'], 'meta/meta.ger3', 'MetaGerSearch@search')->middleware('browserverification', 'humanverification', 'useragentmaster');
 
         Route::get('meta/loadMore', 'MetaGerSearch@loadMore');
         Route::post('img/cat.jpg', 'HumanVerification@remove');
         Route::get('verify/metager/{id}/{uid}', ['as' => 'captcha', 'uses' => 'HumanVerification@captcha', 'middleware' => 'throttle:12,1']);
         Route::get('r/metager/{mm}/{pw}/{url}', ['as' => 'humanverification', 'uses' => 'HumanVerification@removeGet']);
         Route::post('img/dog.jpg', 'HumanVerification@whitelist');
+        Route::get('index.css', 'HumanVerification@browserVerification');
 
         Route::get('meta/picture', 'Pictureproxy@get');
         Route::get('clickstats', 'LogController@clicklog');