NanmiCoder/MediaCrawler · error · DataFetchError
{err_msg}
Error message
{err_msg} What it means
DataFetchError raised by XiaoHongShuClient.request as the final else branch: the API returned HTTP 200 with a JSON body where success is false, the code is not one of the known special codes, and the message is taken from the response's msg field (falling back to the raw body). It is the catch-all for unrecognized xiaohongshu API errors.
Source
Thrown at media_platform/xhs/client.py:196
)
if response_code == str(self.IP_ERROR_CODE):
raise IPBlockError(self.IP_ERROR_STR)
if response_code == str(self.SECURITY_LIMIT_CODE):
raise PlatformAccessError(
f"XHS account security restriction, code: {self.SECURITY_LIMIT_CODE}"
)
if return_response:
return response.text
data: Dict = response_data if response_data is not None else response.json()
if data["success"]:
return data.get("data", data.get("success", {}))
# IP_ERROR_CODE / SECURITY_LIMIT_CODE are already handled above, before return_response.
elif data["code"] in (self.NOTE_NOT_FOUND_CODE, self.NOTE_ABNORMAL_CODE):
raise NoteNotFoundError(f"Note not found or abnormal, code: {data['code']}")
else:
err_msg = data.get("msg", None) or f"{response.text}"
raise DataFetchError(err_msg)
@staticmethod
def _build_query_string(params: Dict) -> str:
"""Build URL query string with encoding matching browser behavior (commas not encoded)"""
parts = []
for key, value in params.items():
value_str = str(value) if value is not None else ""
parts.append(f"{key}={quote(value_str, safe=',')}")
return "&".join(parts)
async def get(self, uri: str, params: Optional[Dict] = None) -> Dict:
"""
GET request, signs request headers
Args:
uri: Request route
params: Request parameters
Returns:View on GitHub (pinned to d6f7c5bb90)
Solutions
- Read the embedded msg from the exception - it is xiaohongshu's own error text and usually names the problem.
- Compare the failing request's params/headers with the same call in a browser devtools session and align them.
- If msg indicates login required, refresh the cookie.
- Update the client to special-case the new code (like NOTE_NOT_FOUND_CODE) if it recurs across calls.
Example fix
// before
# generic pass-through
// after
try:
data = await xhs_client.get(uri, params=params)
except DataFetchError as e:
utils.logger.error(f"xhs api error for {uri}: {e}")
raise Defensive patterns
Strategy: try-catch
Try / catch
from media_platform.xhs.exception import DataFetchError
try:
data = await xhs_client.get(uri, params=params)
except DataFetchError as e:
utils.logger.error(f"xhs business error on {uri}: {e}")
raise Prevention
- Treat msg text in the exception as the authoritative diagnosis from xiaohongshu.
- Mirror browser devtools requests exactly (params, headers, order) when a call keeps failing.
- Special-case newly observed codes in the client instead of letting them hit the generic branch.
When it happens
Trigger: Any xhs API call returning an unexpected business error code - e.g. parameter rejected by the server, unsupported endpoint, or new error codes the client does not special-case. The exact msg string in the exception comes straight from xiaohongshu.
Common situations: xiaohongshu adds a new error code after a site update; malformed query built by a wrapper method; semi-logged-in cookie producing error responses on some endpoints only.
Related errors
- Note not found or abnormal, code: {data['code']}
- {data.error.message}
- response error
- unknown error
- get weibo detail err: {response.text}
AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15).
Data as JSON: /api/errors/0d71b012e04c0b7b.
Report an issue: GitHub.