unclecode/crawl4ai · error · PermissionError

[NSTProxy] API Error: {data.get('msg', 'Unknown error')}

Error message

[NSTProxy] API Error: {data.get('msg', 'Unknown error')}

What it means

Raised as PermissionError when the NSTProxy API responds HTTP 200 but with a JSON object containing a truthy "err" field. The msg field carries the vendor's error text (auth failure, exhausted traffic, invalid channel, etc.). Note: this happens after response.raise_for_status(), so it is an application-level error, not a transport one.

Source

Thrown at crawl4ai/async_configs.py:1092

            "sessionDuration": session_duration,
            "token": token,
        }
        if state:
            params["state"] = state
        if city:
            params["city"] = city

        url = "https://api.nstproxy.com/api/v1/generate/apiproxies"

        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()

            data = response.json()

            # --- Handle API error response ---
            if isinstance(data, dict) and data.get("err"):
                raise PermissionError(f"[NSTProxy] API Error: {data.get('msg', 'Unknown error')}")

            if not isinstance(data, list) or not data:
                raise ValueError("[NSTProxy] Invalid API response — expected a non-empty list")

            proxy_info = data[0]

            # --- Apply proxy config ---
            self.proxy_config = ProxyConfig(
                server=f"{protocol}://{proxy_info['ip']}:{proxy_info['port']}",
                username=proxy_info["username"],
                password=proxy_info["password"],
            )

        except Exception as e:
            print(f"[NSTProxy] ❌ Failed to set proxy: {e}")
            raise

class VirtualScrollConfig:

View on GitHub (pinned to 7e80152142)

Solutions

  1. Read the msg value in the exception — it names the exact vendor-side cause
  2. Verify token and channel_id against the NSTProxy dashboard; regenerate the token if expired
  3. Check remaining traffic/quota on your NSTProxy account and top up or reduce count
  4. If the country/state/city combo is unsupported, retry with country="" or a supported region

Example fix

// before
cfg.set_nstproxy(token=old_token, channel_id=c)  # token rotated server-side
// after
from nstproxy_dashboard import fresh_token  # re-obtain
cfg.set_nstproxy(token=fresh_token, channel_id=c)
Defensive patterns

Strategy: retry

Try / catch

from tenacity import retry, retry_if_exception_type, wait_exponential

@retry(retry=retry_if_exception_type(PermissionError), wait=wait_exponential(min=2, max=30), stop=stop_after_attempt(3))
def setup_proxy(cfg, **kw):
    cfg.set_nstproxy(**kw)
# inspect str(e) for 'API Error' to distinguish vendor-side auth/quota failures

Prevention

When it happens

Trigger: Expired or invalid NSTProxy token; wrong channel_id; account out of bandwidth/traffic; requesting a country not available on your plan — the API returns {"err": ..., "msg": "..."} with status 200.

Common situations: Old token committed to a repo after key rotation; free-plan limits hit mid-crawl; region restrictions on the account.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/022f96463f39cf0a. Report an issue: GitHub.