From e840e3f96025537edbcfa9a5c61a2a05934edfc7 Mon Sep 17 00:00:00 2001 From: Markus Heiser Date: Fri, 17 Oct 2025 16:57:41 +0200 Subject: [PATCH] [fix] engine mullvadleta - ignore HTTP 403 & 429 response It doesn't matter if you're using Mullvad's VPN and a proper browser, you'll still get blocked for specific searches [1] with a 403 or 429 HTTP status code. Mullvad only blocks the search request and doesn't prevent you from doing more searches. The logic should handle the blocked requests (403, 429), but not put the engine on a cooldown. [1] https://leta.mullvad.net/search?q=site%3Afoo+bar&engine=brave Closes: https://github.com/searxng/searxng/issues/5328 Signed-off-by: Markus Heiser --- searx/engines/mullvad_leta.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/searx/engines/mullvad_leta.py b/searx/engines/mullvad_leta.py index 0ad549b35..f494e812d 100644 --- a/searx/engines/mullvad_leta.py +++ b/searx/engines/mullvad_leta.py @@ -43,9 +43,12 @@ import babel from httpx import Response from lxml import html from searx.enginelib.traits import EngineTraits +from searx.extended_types import SXNG_Response + from searx.locales import get_official_locales, language_tag, region_tag from searx.utils import eval_xpath_list from searx.result_types import EngineResults, MainResult +from searx.network import raise_for_httperror search_url = "https://leta.mullvad.net" @@ -112,7 +115,8 @@ class DataNodeResultIndices(t.TypedDict): favicon: int -def request(query: str, params: dict): +def request(query: str, params: dict[str, t.Any]) -> None: + params["raise_for_httperror"] = False params["method"] = "GET" args = { "q": query, @@ -136,10 +140,19 @@ def request(query: str, params: dict): params["url"] = f"{search_url}/search/__data.json?{urlencode(args)}" - return params +def response(resp: SXNG_Response) -> EngineResults: + results = EngineResults() + + if resp.status_code in (403, 429): + # It doesn't matter if you're using Mullvad's VPN and a proper browser, + # you'll still get blocked for specific searches with a 403 or 429 HTTP + # status code. + # https://github.com/searxng/searxng/issues/5328#issue-3518337233 + return results + # raise for other errors + raise_for_httperror(resp) -def response(resp: Response) -> EngineResults: json_response = resp.json() nodes = json_response["nodes"] @@ -159,7 +172,6 @@ def response(resp: Response) -> EngineResults: query_items_indices = query_meta_data["items"] - results = EngineResults() for idx in data_nodes[query_items_indices]: query_item_indices: DataNodeResultIndices = data_nodes[idx] results.add(