NanmiCoder/MediaCrawler · error · Exception

get ip error from proxy provider and code not 0 ...

Error message

get ip error from proxy provider and  code not 0 ...

What it means

Raised when the KuaiDaiLi API responds with HTTP 200 but the JSON body's 'code' field is not 0 — the provider's application-level error channel. The provider's 'msg' field is logged before raising. Typical codes signal exhausted extraction quota for the time window, invalid order, parameter errors, or signature problems that passed the HTTP layer.

Source

Thrown at proxy/providers/kuaidl_proxy.py:127

        if len(ip_cache_list) >= num:
            return ip_cache_list[:num]

        # If the quantity in cache is insufficient, get from IP provider to supplement, then store in cache
        need_get_count = num - len(ip_cache_list)
        self.params.update({"num": need_get_count})

        ip_infos: List[IpInfoModel] = []
        async with make_async_client() as client:
            response = await client.get(self.api_base + uri, params=self.params)

            if response.status_code != 200:
                utils.logger.error(f"[KuaiDaiLiProxy.get_proxies] statuc code not 200 and response.txt:{response.text}, status code: {response.status_code}")
                raise Exception("get ip error from proxy provider and status code not 200 ...")

            ip_response: Dict = response.json()
            if ip_response.get("code") != 0:
                utils.logger.error(f"[KuaiDaiLiProxy.get_proxies]  code not 0 and msg:{ip_response.get('msg')}")
                raise Exception("get ip error from proxy provider and  code not 0 ...")

            proxy_list: List[str] = ip_response.get("data", {}).get("proxy_list")
            for proxy in proxy_list:
                proxy_model = parse_kuaidaili_proxy(proxy)
                # expire_ts is relative time (seconds), needs to be converted to absolute timestamp
                # Consider expired DELTA_EXPIRED_SECOND seconds in advance to avoid critical time usage failure
                ip_info_model = IpInfoModel(
                    ip=proxy_model.ip,
                    port=proxy_model.port,
                    user=self.kdl_user_name,
                    password=self.kdl_user_pwd,
                    expired_time_ts=proxy_model.expire_ts + utils.get_unix_timestamp() - DELTA_EXPIRED_SECOND,

                )
                ip_key = f"{self.proxy_brand_name}_{ip_info_model.ip}_{ip_info_model.port}"
                # Cache expiration time uses relative time (seconds), also needs to subtract buffer time
                self.ip_cache.set_ip(ip_key, ip_info_model.model_dump_json(), ex=proxy_model.expire_ts - DELTA_EXPIRED_SECOND)
                ip_infos.append(ip_info_model)

View on GitHub (pinned to d6f7c5bb90)

Solutions

  1. Check the logged msg text — it names the exact provider error (quota, order status, param)
  2. If quota-exhaustion: wait for the window to reset (usually 60s) and retry with a smaller num
  3. Confirm the KuaiDaiLi order is active and has balance; re-enable it in the provider console
  4. Cap need_get_count so a single request never exceeds the order's per-request/per-minute limit and refill in batches
  5. Catch IpGetError at the pool level and fall back to serving cached IPs while the provider recovers

Example fix

// before
need_get_count = num - len(ip_cache_list)
self.params.update({"num": need_get_count})

// after (cap per-request quantity)
need_get_count = min(num - len(ip_cache_list), KDL_MAX_PER_REQUEST)
self.params.update({"num": need_get_count})
Defensive patterns

Strategy: retry

Try / catch

try:
    infos = await kdl.get_proxies(num=need)
except Exception as e:  # code != 0 path
    msg = str(e)
    if "code not 0" in msg:
        await asyncio.sleep(60)  # quota window reset
        infos = await kdl.get_proxies(num=min(need, 5))
    else:
        raise

Prevention

When it happens

Trigger: GET /GetKdlIp succeeds at HTTP level but returns {'code': ..., 'msg': ...} — e.g. asking for more IPs than the order's per-minute allowance, order expired/not active, bad 'num' parameter (note need_get_count is computed as num - len(ip_cache_list) and could be large), or wrong signature producing a JSON error body with 200.

Common situations: Exhausting the daily/minute IP quota during a long crawl; KuaiDaili order expired or in arrears; requesting a big burst of IPs when the cache is empty (need_get_count == full pool size); signature generated with a stale timestamp.

Related errors


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