summaryrefslogtreecommitdiff
path: root/searx/engines
diff options
context:
space:
mode:
authorBnyro <bnyro@tutanota.com>2026-06-29 19:49:28 +0200
committerBnyro <bnyro@tutanota.com>2026-06-30 15:23:09 +0200
commit6b2ec018e23c60ec5ed6c5b0b7a5e823ce5d0c9e (patch)
tree3f732e4ba7bfd90c570ad5a961adf7063b938be7 /searx/engines
parentbfeaad6c376c9dc1d402456699e03139bbac4514 (diff)
[fix] qwant: access denied due to mismatching query order
We're now shuffling the order of query arguments, as it seems that Qwant actively blocks the query order of SearXNG. tgp seems to be short for "test group" (look at the XHR requests the browser sends to "https://www.qwant.com/action/ui") - its actual value doesn't matter, as long as it's sent and at the correct position in the query params and doesn't change too frequently
Diffstat (limited to 'searx/engines')
-rw-r--r--searx/engines/qwant.py16
1 files changed, 14 insertions, 2 deletions
diff --git a/searx/engines/qwant.py b/searx/engines/qwant.py
index 0e75ee559..1c690146c 100644
--- a/searx/engines/qwant.py
+++ b/searx/engines/qwant.py
@@ -38,6 +38,7 @@ Implementations
"""
+import random
import typing as t
from datetime import (
@@ -89,6 +90,11 @@ qwant_categ: str = None # pyright: ignore[reportAssignmentType]
safesearch = True
+# tgp seems to be short for "test group" - its actual value doesn't matter, as
+# long as it's sent and at the correct position in the query params and doesn't
+# change too frequently
+test_group_value = random.randint(1, 3)
+
# fmt: off
qwant_news_locales = [
"ca_ad", "ca_es", "ca_fr", "co_fr", "de_at", "de_ch", "de_de", "en_au",
@@ -114,17 +120,24 @@ def request(query: str, params: "OnlineParams") -> None:
results_per_page = 10
if qwant_categ == "images":
results_per_page = 50
+
args = {
"q": query,
"count": results_per_page,
"locale": q_locale,
"offset": (params["pageno"] - 1) * results_per_page,
+ "tgp": test_group_value,
"device": "desktop",
"safesearch": params["safesearch"],
- "tgp": 1,
"display": True,
"llm": True,
}
+
+ # shuffle query parameters to be harder to fingerprint
+ args = list(args.items())
+ random.shuffle(args)
+ args = dict(args)
+
params["raise_for_httperror"] = False
params["url"] = f"{api_url}{qwant_categ}?{urlencode(args)}"
@@ -190,7 +203,6 @@ def response(resp: "SXNG_Response") -> EngineResults:
mainline_items: list[dict[str, t.Any]] = row.get("items", [])
for item in mainline_items:
-
title: str = item.get("title", "")
res_url: str = item.get("url", "")
pub_date: datetime | None = None