NanmiCoder/MediaCrawler · error

params or payload is required

Error message

params or payload is required

What it means

Raised by XiaoHongShuClient's request-signing helper (_pre_headers) when neither query params nor a POST payload was supplied. Signing with the xhshow algorithm requires the exact data that will be sent, so the method refuses to sign an empty request. It is a ValueError indicating a programming error in the caller.

Source

Thrown at media_platform/xhs/client.py:108

    async def _pre_headers(self, url: str, params: Optional[Dict] = None, payload: Optional[Dict] = None) -> Dict:
        """请求头参数签名 (使用 xhshow 纯算法)

        Args:
            url: 请求 URI path
            params: GET 请求参数
            payload: POST 请求参数

        Returns:
            Dict: 签名后的请求头参数
        """
        if params is not None:
            data = params
            method = "GET"
        elif payload is not None:
            data = payload
            method = "POST"
        else:
            raise ValueError("params or payload is required")

        # 使用 xhshow 纯算法生成签名
        signs = sign_with_xhshow(
            uri=url,
            data=data,
            cookie_str=self.headers.get("Cookie", ""),
            method=method,
        )

        headers = {
            "X-S": signs["x-s"],
            "X-T": signs["x-t"],
            "x-S-Common": signs["x-s-common"],
            "X-B3-Traceid": signs["x-b3-traceid"],
        }
        self.headers.update(headers)
        return self.headers

View on GitHub (pinned to d6f7c5bb90)

Solutions

  1. Find the xhs client method that made the call and make sure its params/payload argument is actually passed through to _pre_headers.
  2. Validate upstream inputs (e.g. KEYWORDS) are non-empty before starting an xhs crawl.
  3. Pass an empty dict explicitly only if the endpoint truly takes no parameters - otherwise supply the real query.

Example fix

# before
async def get_note_comments(note_id: str):
    return await self.get("/api/sns/web/v2/comment/page", params=None)
# after
async def get_note_comments(note_id: str, cursor=""):
    params = {"note_id": note_id, "cursor": cursor}
    return await self.get("/api/sns/web/v2/comment/page", params=params)
Defensive patterns

Strategy: validation

Validate before calling

def has_request_data(params, payload) -> bool:
    return params is not None or payload is not None

Prevention

When it happens

Trigger: Calling a GET API method with params=None, or a POST method with payload=None, e.g. get_note_info_with_zero_param on an empty keyword or a search call built from empty user input.

Common situations: A new endpoint wrapper added without forwarding its params argument; empty search keyword from config; refactor that dropped the payload argument.

Related errors


AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15). Data as JSON: /api/errors/235fce905de25bc6. Report an issue: GitHub.