> ## Documentation Index
> Fetch the complete documentation index at: https://help.miyaip.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MiyaIP dynamic proxy API: generate residential or mobile proxies

> Generate MiyaIP dynamic residential or mobile proxy details using Crc and KeyName, with location, session, protocol, and output format settings.

export const MiyaApiPlayground = ({specUrl, method, path, locale = "en"}) => {
  const miyaApiOrigin = "https://miyaip.com";
  const miyaResponseLimit = 200 * 1024;
  const miyaAllowedOperations = ["POST /api/SysLogin/Login", "GET /api/ProxyLogic/Generate", "POST /api/UserShort/GenerateIps", "GET /api/ProxyLogic/UnlimitedGenerate", "GET /api/SysLogin/GetUserInfo", "GET /api/ProxyLogic/BandwidthAnalysis", "GET /api/UserIsps/PageList", "GET /api/DatacenterIps/PageList"];
  const miyaAllowedSpecs = ["/api-reference/openapi.zh.json", "/api-reference/openapi.en.json"];
  const miyaSensitiveKey = /password|passwd|pwd|token|secret|authorization|^crc$|keyname|key$|api.?key|user.?name|proxy.?user|proxy.?pass|full.?proxy/i;
  const miyaLabels = locale => locale === "zh" ? {
    title: "在线调试",
    loading: "正在加载接口配置…",
    loadError: "无法加载接口配置。请刷新页面后重试。",
    unsupported: "此调试器仅支持文档中列出的 MiyaIP 接口。",
    request: "请求预览（凭据已隐藏）",
    send: "发送请求",
    sending: "请求中…",
    cancel: "取消请求",
    clear: "清空",
    optional: "可选",
    required: "必填",
    requiredError: "请填写此项。",
    integerError: "请输入整数。",
    emailError: "请输入有效的邮箱地址。",
    enumError: "请选择文档列出的选项。",
    minimum: "最小值为",
    maximum: "最大值为",
    live: "点击发送会向 MiyaIP 发送实际请求。凭据和响应仅保存在本页面的内存中。",
    cancelNote: "超时或取消只会停止浏览器等待，不能保证服务器撤销请求；调试器不会自动重试。",
    response: "响应",
    elapsed: "耗时",
    status: "HTTP 状态",
    contentType: "响应类型",
    businessCode: "业务 code",
    httpSuccess: "HTTP 请求完成",
    businessSuccess: "业务 code 表示成功",
    businessError: "接口返回业务错误",
    httpError: "接口返回 HTTP 错误",
    networkError: "请求失败。请检查网络、跨域策略及连接状态。",
    timeout: "等待超过 30 秒，请求已停止等待。",
    cancelled: "已取消等待响应。",
    truncated: "响应超过 200 KiB，展示内容已截断；不能据此判断完整 JSON 或业务结果。",
    invalidJson: "响应无法解析为 JSON，请检查响应类型和原始返回内容。",
    jsonHidden: "为避免泄露敏感字段，不展示截断或无法解析的 JSON 正文。",
    empty: "响应正文为空。",
    showProxy: "显示代理连接信息",
    hideProxy: "隐藏代理连接凭据",
    token: "登录 Token",
    showToken: "显示 Token",
    hideToken: "隐藏 Token",
    copyToken: "复制 Token",
    copied: "已复制 Token。",
    copyFailed: "复制失败，请显示 Token 后手动复制。",
    masked: "敏感字段默认隐藏。",
    proxyMasked: "代理连接凭据默认隐藏，可主动显示完整原文。"
  } : {
    title: "Try this API",
    loading: "Loading the API configuration…",
    loadError: "The API configuration could not be loaded. Refresh this page and try again.",
    unsupported: "This form only supports the MiyaIP endpoints listed in these docs.",
    request: "Request preview (credentials hidden)",
    send: "Send request",
    sending: "Sending…",
    cancel: "Cancel request",
    clear: "Clear",
    optional: "Optional",
    required: "Required",
    requiredError: "Enter a value.",
    integerError: "Enter a whole number.",
    emailError: "Enter a valid email address.",
    enumError: "Select one of the documented options.",
    minimum: "The minimum is",
    maximum: "The maximum is",
    live: "Sending makes a real request to MiyaIP. Credentials and responses remain in memory on this page only.",
    cancelNote: "A timeout or cancellation stops the browser from waiting; it does not guarantee that the server cancels the request. This form never retries automatically.",
    response: "Response",
    elapsed: "Elapsed",
    status: "HTTP status",
    contentType: "Content type",
    businessCode: "Business code",
    httpSuccess: "HTTP request completed",
    businessSuccess: "The business code indicates success",
    businessError: "The API returned a business error",
    httpError: "The API returned an HTTP error",
    networkError: "The request failed. Check the network, CORS policy, and connection status.",
    timeout: "The 30-second wait expired. The browser stopped waiting.",
    cancelled: "Stopped waiting for the response.",
    truncated: "The response exceeds 200 KiB and has been truncated. A partial response cannot confirm a complete JSON or business result.",
    invalidJson: "The response could not be parsed as JSON. Check its content type and returned content.",
    jsonHidden: "A truncated or unparseable JSON body is not displayed, so its sensitive fields cannot be exposed.",
    empty: "The response body is empty.",
    showProxy: "Show proxy credentials",
    hideProxy: "Hide proxy credentials",
    token: "Login token",
    showToken: "Show token",
    hideToken: "Hide token",
    copyToken: "Copy token",
    copied: "Token copied.",
    copyFailed: "Copy failed. Show the token and copy it manually.",
    masked: "Sensitive fields are hidden by default.",
    proxyMasked: "Proxy credentials are hidden by default. You can explicitly show the original text."
  };
  const miyaActiveFields = (fields, values) => fields.filter(field => !field.showWhen || Object.entries(field.showWhen).every(([name, expected]) => String(values[name]) === String(expected)));
  const miyaDefaultValues = fields => Object.fromEntries(fields.map(field => [field.name, field.defaultValue === undefined || field.defaultValue === null ? "" : String(field.defaultValue)]));
  const miyaValidate = (fields, values, labels) => {
    const errors = {};
    miyaActiveFields(fields, values).forEach(field => {
      const value = String(values[field.name] ?? "").trim();
      if (!value) {
        if (field.required) errors[field.name] = labels.requiredError;
        return;
      }
      if (field.type === "integer") {
        const number = Number(value);
        if (!(/^-?\d+$/).test(value) || !Number.isSafeInteger(number)) errors[field.name] = labels.integerError; else if (field.min !== undefined && number < field.min) errors[field.name] = `${labels.minimum} ${field.min}.`; else if (field.max !== undefined && number > field.max) errors[field.name] = `${labels.maximum} ${field.max}.`;
      }
      if (field.input === "email" && !(/^[^\s@]+@[^\s@]+\.[^\s@]+$/).test(value)) errors[field.name] = labels.emailError;
      if (field.options?.length && !field.options.some(option => String(option.value) === value)) errors[field.name] = labels.enumError;
    });
    return errors;
  };
  const miyaBearerToken = value => String(value).trim().replace(/^Bearer\s+/i, "").trim();
  const miyaKnownSecrets = (fields, values) => miyaActiveFields(fields, values).filter(field => field.sensitive || field.in === "header" || miyaSensitiveKey.test(field.name)).flatMap(field => {
    const raw = String(values[field.name] ?? "");
    return field.in === "header" ? [raw, raw.trim(), miyaBearerToken(raw)] : [raw];
  }).filter(Boolean).sort((a, b) => b.length - a.length);
  const miyaMaskString = (text, secrets = []) => {
    let masked = String(text);
    secrets.forEach(secret => {
      const formEncoded = new URLSearchParams([["value", secret]]).toString().slice(("value=").length);
      [...new Set([secret, encodeURIComponent(secret), formEncoded])].sort((a, b) => b.length - a.length).forEach(variant => {
        masked = masked.split(variant).join("[hidden]");
      });
    });
    return masked.replace(/((?:https?|socks5?h?):\/\/)[^\s/@]+(?::[^\s/@]*)?@/gi, "$1[hidden]@").replace(/(^|\n)(\s*)[^\r\n\s@]+@([^\r\n]+)/g, "$1$2[hidden]@$3").replace(/(^|\n)(\s*)[^:\s]+:[^:\s]+:(\[[^\]\s]+\]|[^:\s]+):(\d+)(?=\r?\n|$)/g, "$1$2[hidden]:[hidden]:$3:$4").replace(/(^|\n)(\s*(?:\[[^\]\s]+\]|[^\s:]+):\d+:)[^\r\n]+/g, "$1$2[hidden]:[hidden]");
  };
  const miyaRedactJson = (value, secrets = []) => {
    if (Array.isArray(value)) return value.map(item => miyaRedactJson(item, secrets));
    if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, miyaSensitiveKey.test(key) && item !== null && item !== "" && ["string", "object"].includes(typeof item) ? "[hidden]" : miyaRedactJson(item, secrets)]));
    return typeof value === "string" ? miyaMaskString(value, secrets) : value;
  };
  const miyaMaskProxyText = (text, format, secrets) => String(text).split("\n").map(line => {
    if (!line.trim()) return line;
    let masked;
    if (String(format) === "0") masked = line.replace(/^(\s*(?:\[[^\]\s]+\]|[^:\s]+):\d+):[^\r\n]+$/, "$1:[hidden]:[hidden]"); else if (String(format) === "1") masked = line.replace(/^(\s*)[^\r\n]+@([^\r\n]+)$/, "$1[hidden]@$2"); else if (String(format) === "2") masked = line.replace(/^(\s*)[^\r\n]+:(\[[^\]\s]+\]|[^:\s]+):(\d+)\s*$/, "$1[hidden]:[hidden]:$2:$3");
    return masked && masked !== line ? miyaMaskString(masked, secrets) : "[hidden]";
  }).join("\n");
  const miyaFindToken = value => {
    if (!value || typeof value !== "object") return "";
    for (const [key, item] of Object.entries(value)) {
      if ((/^(?:token|access_?token|jwt)$/i).test(key) && typeof item === "string" && item) return item;
      if (item && typeof item === "object") {
        const found = miyaFindToken(item);
        if (found) return found;
      }
    }
    return "";
  };
  const miyaBuildRequest = (method, path, fields, values, redacted = false) => {
    if (!miyaAllowedOperations.includes(`${method} ${path}`)) throw new Error("Unsupported operation");
    const url = new URL(path, miyaApiOrigin);
    const headers = {
      Accept: "application/json, text/plain"
    };
    const body = {};
    miyaActiveFields(fields, values).forEach(field => {
      const raw = String(values[field.name] ?? "");
      if (!raw.trim()) return;
      const sensitive = field.sensitive || field.in === "header" || miyaSensitiveKey.test(field.name);
      const value = redacted && sensitive ? "[hidden]" : field.type === "integer" ? Number(raw) : raw;
      if (field.in === "header") {
        headers.Authorization = redacted ? "Bearer [hidden]" : `Bearer ${miyaBearerToken(raw)}`;
      } else if (field.in === "query") url.searchParams.set(field.name, String(value)); else if (field.in === "body") body[field.name] = value;
    });
    const init = {
      method,
      headers,
      credentials: "omit",
      mode: "cors",
      redirect: "error"
    };
    if (method === "POST") {
      headers["Content-Type"] = "application/json";
      init.body = JSON.stringify(body);
    }
    return {
      url: url.toString(),
      init
    };
  };
  const miyaReadResponse = async (response, limit = miyaResponseLimit) => {
    if (!response.body?.getReader) {
      const bytes = new TextEncoder().encode(await response.text());
      return {
        text: new TextDecoder().decode(bytes.subarray(0, limit)),
        truncated: bytes.length > limit
      };
    }
    const reader = response.body.getReader();
    const chunks = [];
    let size = 0;
    let truncated = false;
    try {
      while (true) {
        const {value, done} = await reader.read();
        if (done) break;
        const remaining = limit - size;
        if (value.byteLength > remaining) {
          if (remaining > 0) chunks.push(value.subarray(0, remaining));
          size = limit;
          truncated = true;
          await reader.cancel();
          break;
        }
        chunks.push(value);
        size += value.byteLength;
      }
    } finally {
      reader.releaseLock();
    }
    const bytes = new Uint8Array(size);
    let offset = 0;
    chunks.forEach(chunk => {
      bytes.set(chunk, offset);
      offset += chunk.byteLength;
    });
    return {
      text: new TextDecoder().decode(bytes),
      truncated
    };
  };
  const miyaParseResponse = (response, payload, method, path, secrets, outputFormat) => {
    const contentType = response.headers.get("content-type") || "";
    const expectsText = method === "GET" && ["/api/ProxyLogic/Generate", "/api/ProxyLogic/UnlimitedGenerate"].includes(path);
    let parsed = null;
    let invalidJson = false;
    if (!payload.truncated && payload.text.trim() && (contentType.includes("json") || !expectsText)) {
      try {
        parsed = JSON.parse(payload.text);
      } catch {
        invalidJson = true;
      }
    }
    const code = parsed && !Array.isArray(parsed) && typeof parsed === "object" ? parsed.code : undefined;
    const codeSuccess = code === 0 || code === 200 || code === "0" || code === "200";
    const kind = !response.ok ? "httpError" : payload.truncated ? "truncated" : invalidJson ? "invalidJson" : code !== undefined ? codeSuccess ? "businessSuccess" : "businessError" : "httpSuccess";
    const token = path === "/api/SysLogin/Login" && response.ok && !payload.truncated && kind !== "businessError" ? miyaFindToken(parsed) : "";
    const textResponse = parsed === null && expectsText && !contentType.includes("json");
    const hiddenJson = !textResponse && (payload.truncated || invalidJson);
    return {
      status: response.status,
      contentType,
      kind,
      code,
      truncated: payload.truncated,
      rawText: payload.text,
      textResponse,
      hiddenJson,
      token,
      maskedText: hiddenJson ? "" : parsed !== null ? JSON.stringify(miyaRedactJson(parsed, [...secrets, token].filter(Boolean)), null, 2) : textResponse ? miyaMaskProxyText(payload.text, outputFormat, secrets) : miyaMaskString(payload.text, [...secrets, token].filter(Boolean))
    };
  };
  const labels = useMemo(() => miyaLabels(locale), [locale]);
  const [config, setConfig] = useState(null);
  const [values, setValues] = useState({});
  const [errors, setErrors] = useState({});
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState("");
  const [pending, setPending] = useState(false);
  const [result, setResult] = useState(null);
  const [showToken, setShowToken] = useState(false);
  const [showProxy, setShowProxy] = useState(false);
  const [notice, setNotice] = useState("");
  const requestRef = useRef(null);
  const sequenceRef = useRef(0);
  const liveRef = useRef(false);
  useEffect(() => {
    liveRef.current = true;
    sequenceRef.current += 1;
    requestRef.current?.controller.abort();
    requestRef.current = null;
    setConfig(null);
    setValues({});
    setErrors({});
    setResult(null);
    setShowToken(false);
    setShowProxy(false);
    setNotice("");
    setPending(false);
    setLoading(true);
    setLoadError("");
    const specController = new AbortController();
    let current = true;
    const load = async () => {
      if (!miyaAllowedSpecs.includes(specUrl) || !miyaAllowedOperations.includes(`${method} ${path}`)) {
        if (current) {
          setLoadError(labels.unsupported);
          setLoading(false);
        }
        return;
      }
      try {
        const response = await fetch(specUrl, {
          credentials: "omit",
          signal: specController.signal
        });
        if (!response.ok) throw new Error("Configuration unavailable");
        const spec = await response.json();
        const metadata = spec.paths?.[path]?.[method.toLowerCase()]?.["x-miya-playground"];
        if (!metadata || !Array.isArray(metadata.fields) || !metadata.fields.every(field => typeof field.name === "string" && ["query", "body", "header"].includes(field.in))) throw new Error("Invalid configuration");
        if (current) {
          setConfig(metadata);
          setValues(miyaDefaultValues(metadata.fields));
        }
      } catch (error) {
        if (current && !specController.signal.aborted) setLoadError(labels.loadError);
      } finally {
        if (current) setLoading(false);
      }
    };
    load();
    return () => {
      current = false;
      liveRef.current = false;
      sequenceRef.current += 1;
      specController.abort();
      requestRef.current?.controller.abort();
      requestRef.current = null;
    };
  }, [specUrl, method, path, locale]);
  const fields = config?.fields || [];
  const activeFields = miyaActiveFields(fields, values);
  const preview = useMemo(() => {
    if (!config) return "";
    try {
      const request = miyaBuildRequest(method, path, config.fields, values, true);
      return `${method} ${request.url}\n${Object.entries(request.init.headers).map(([key, value]) => `${key}: ${value}`).join("\n")}${request.init.body ? `\n\n${JSON.stringify(JSON.parse(request.init.body), null, 2)}` : ""}`;
    } catch {
      return "";
    }
  }, [config, values, method, path]);
  const updateValue = (name, value) => {
    setValues(previous => ({
      ...previous,
      [name]: value
    }));
    setErrors(previous => {
      const next = {
        ...previous
      };
      delete next[name];
      return next;
    });
  };
  const cancel = () => {
    const active = requestRef.current;
    if (!active) return;
    sequenceRef.current += 1;
    active.controller.abort();
    requestRef.current = null;
    setPending(false);
    setResult({
      kind: "cancelled",
      elapsed: Math.round(performance.now() - active.started)
    });
    setShowToken(false);
    setShowProxy(false);
    setNotice("");
  };
  const clear = () => {
    sequenceRef.current += 1;
    requestRef.current?.controller.abort();
    requestRef.current = null;
    setValues(miyaDefaultValues(fields));
    setErrors({});
    setResult(null);
    setShowToken(false);
    setShowProxy(false);
    setNotice("");
    setPending(false);
  };
  const submit = async event => {
    event.preventDefault();
    if (!config || requestRef.current || !liveRef.current) return;
    const nextErrors = miyaValidate(fields, values, labels);
    setErrors(nextErrors);
    if (Object.keys(nextErrors).length) return;
    const controller = new AbortController();
    const serial = ++sequenceRef.current;
    const started = performance.now();
    requestRef.current = {
      controller,
      serial,
      started
    };
    setPending(true);
    setResult(null);
    setShowToken(false);
    setShowProxy(false);
    setNotice("");
    let timedOut = false;
    let status;
    let contentType;
    const timeout = setTimeout(() => {
      timedOut = true;
      controller.abort();
    }, 30000);
    try {
      const request = miyaBuildRequest(method, path, fields, values);
      const response = await fetch(request.url, {
        ...request.init,
        signal: controller.signal
      });
      status = response.status;
      contentType = response.headers.get("content-type") || "";
      const payload = await miyaReadResponse(response);
      const parsed = miyaParseResponse(response, payload, method, path, miyaKnownSecrets(fields, values), values.Format);
      if (liveRef.current && sequenceRef.current === serial) setResult({
        ...parsed,
        elapsed: Math.round(performance.now() - started)
      });
    } catch {
      if (liveRef.current && sequenceRef.current === serial) setResult({
        kind: timedOut ? "timeout" : controller.signal.aborted ? "cancelled" : "networkError",
        status,
        contentType,
        elapsed: Math.round(performance.now() - started)
      });
    } finally {
      clearTimeout(timeout);
      if (requestRef.current?.serial === serial) requestRef.current = null;
      if (liveRef.current && sequenceRef.current === serial) setPending(false);
    }
  };
  const copyToken = async () => {
    if (!result?.token) return;
    const serial = sequenceRef.current;
    try {
      await navigator.clipboard.writeText(result.token);
      if (liveRef.current && sequenceRef.current === serial) setNotice(labels.copied);
    } catch {
      if (liveRef.current && sequenceRef.current === serial) setNotice(labels.copyFailed);
    }
  };
  const border = "1px solid rgba(128, 128, 128, 0.35)";
  const inputStyle = {
    width: "100%",
    minWidth: 0,
    border,
    borderRadius: "8px",
    padding: "8px 10px",
    background: "transparent",
    color: "inherit",
    font: "inherit",
    colorScheme: "inherit"
  };
  const buttonStyle = {
    border,
    borderRadius: "8px",
    padding: "8px 12px",
    background: "transparent",
    color: "inherit",
    cursor: "pointer",
    font: "inherit",
    fontSize: "14px"
  };
  const preStyle = {
    border,
    borderRadius: "8px",
    padding: "12px",
    maxHeight: "420px",
    overflow: "auto",
    whiteSpace: "pre-wrap",
    overflowWrap: "anywhere",
    fontSize: "13px",
    lineHeight: 1.6,
    background: "rgba(128, 128, 128, 0.06)",
    color: "inherit"
  };
  const hasResponseBody = result && result.rawText !== undefined;
  const responseText = hasResponseBody ? result.hiddenJson ? labels.jsonHidden : result.textResponse && showProxy ? result.rawText : result.maskedText : "";
  return <section data-miya-api-playground="true" aria-label={labels.title} style={{
    border,
    borderRadius: "12px",
    padding: "20px",
    margin: "24px 0",
    color: "inherit"
  }}>
      <h3 style={{
    marginTop: 0
  }}>{labels.title}</h3>
      {loading && <p role="status">{labels.loading}</p>}
      {loadError && <p role="alert">{loadError}</p>}
      {config && !loading && <>
          <p style={{
    fontSize: "14px",
    lineHeight: 1.6
  }}>{labels.live}</p>
          {config.warning && <p style={{
    borderLeft: "3px solid #ef7025",
    paddingLeft: "12px",
    fontSize: "14px"
  }}>{config.warning}</p>}
          <form onSubmit={submit} noValidate>
            <div style={{
    display: "grid",
    gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 240px), 1fr))",
    gap: "16px",
    margin: "18px 0"
  }}>
              {activeFields.map(field => <label key={field.name} style={{
    display: "block",
    minWidth: 0
  }}>
                  <span style={{
    display: "block",
    marginBottom: "6px",
    fontSize: "14px",
    fontWeight: 600
  }}>
                    {field.label || field.name} <span style={{
    fontWeight: 400,
    opacity: 0.7
  }}>({field.required ? labels.required : labels.optional})</span>
                  </span>
                  {field.input === "select" || field.options?.length ? <select name={field.name} value={values[field.name] ?? ""} disabled={pending} style={inputStyle} aria-invalid={Boolean(errors[field.name])} onChange={event => updateValue(field.name, event.target.value)}>
                      {!field.options?.some(option => String(option.value) === "") && <option value="">—</option>}
                      {(field.options || []).map(option => <option key={String(option.value)} value={String(option.value)}>{option.label || String(option.value)}</option>)}
                    </select> : <input name={field.name} type={field.sensitive || field.in === "header" ? "password" : field.input || (field.type === "integer" ? "number" : "text")} value={values[field.name] ?? ""} placeholder={field.placeholder || ""} min={field.min} max={field.max} step={field.type === "integer" ? 1 : undefined} disabled={pending} autoComplete="off" spellCheck={false} aria-invalid={Boolean(errors[field.name])} onChange={event => updateValue(field.name, event.target.value)} style={inputStyle} />}
                  {field.description && <span style={{
    display: "block",
    fontSize: "12px",
    lineHeight: 1.5,
    opacity: 0.75,
    marginTop: "5px"
  }}>{field.description}</span>}
                  {errors[field.name] && <span role="alert" style={{
    display: "block",
    fontSize: "13px",
    color: "#ef7025",
    marginTop: "4px"
  }}>{errors[field.name]}</span>}
                </label>)}
            </div>
            <details style={{
    margin: "16px 0"
  }}>
              <summary style={{
    cursor: "pointer",
    fontSize: "14px"
  }}>{labels.request}</summary>
              <pre data-miya-request-preview="true" style={preStyle}>{preview}</pre>
            </details>
            <div style={{
    display: "flex",
    flexWrap: "wrap",
    gap: "8px"
  }}>
              <button type="submit" disabled={pending} style={{
    ...buttonStyle,
    background: "#ef7025",
    color: "#fff",
    borderColor: "#ef7025",
    opacity: pending ? 0.6 : 1
  }}>
                {pending ? labels.sending : config.submitLabel || labels.send}
              </button>
              {pending && <button type="button" onClick={cancel} style={buttonStyle}>{labels.cancel}</button>}
              <button type="button" onClick={clear} style={buttonStyle}>{labels.clear}</button>
            </div>
          </form>
          <p style={{
    fontSize: "12px",
    lineHeight: 1.6,
    opacity: 0.75
  }}>{labels.cancelNote}</p>
          {result && <div data-miya-response="true" aria-live="polite" style={{
    marginTop: "20px"
  }}>
              <h4 style={{
    marginBottom: "8px"
  }}>{labels.response}</h4>
              <p role={["networkError", "timeout", "httpError", "businessError", "invalidJson"].includes(result.kind) ? "alert" : "status"}>
                {labels[result.kind] || labels.httpSuccess}
              </p>
              <p style={{
    fontSize: "13px",
    display: "flex",
    flexWrap: "wrap",
    gap: "12px"
  }}>
                {result.status !== undefined && <span>{labels.status}: <strong>{result.status}</strong></span>}
                <span>{labels.elapsed}: {result.elapsed} ms</span>
                {result.code !== undefined && <span>{labels.businessCode}: <strong>{String(result.code)}</strong></span>}
                {result.contentType && <span>{labels.contentType}: {result.contentType}</span>}
              </p>
              {result.truncated && result.kind !== "truncated" && <p>{labels.truncated}</p>}
              {result.token && <div style={{
    border,
    borderRadius: "8px",
    padding: "12px",
    margin: "12px 0"
  }}>
                  <p style={{
    margin: "0 0 8px",
    fontSize: "14px"
  }}>{labels.token}: <code style={{
    overflowWrap: "anywhere"
  }}>{showToken ? result.token : "••••••••"}</code></p>
                  <div style={{
    display: "flex",
    flexWrap: "wrap",
    gap: "8px"
  }}>
                    <button type="button" onClick={() => setShowToken(shown => !shown)} style={buttonStyle}>{showToken ? labels.hideToken : labels.showToken}</button>
                    <button type="button" onClick={copyToken} style={buttonStyle}>{labels.copyToken}</button>
                  </div>
                  {notice && <p role="status" style={{
    fontSize: "13px",
    marginBottom: 0
  }}>{notice}</p>}
                </div>}
              {hasResponseBody && <>
                  <p style={{
    fontSize: "12px",
    opacity: 0.75
  }}>{result.textResponse ? labels.proxyMasked : labels.masked}</p>
                  {result.textResponse && <button type="button" onClick={() => setShowProxy(shown => !shown)} style={buttonStyle}>{showProxy ? labels.hideProxy : labels.showProxy}</button>}
                  <pre data-miya-response-body="true" style={preStyle}>{responseText || labels.empty}</pre>
                </>}
            </div>}
        </>}
    </section>;
};

Generate dynamic proxy connection details for the selected country or city. The same endpoint supports dynamic residential and mobile products with the corresponding product credentials.

## Prepare the generation request

1. Obtain `Crc` and the product's key from your dashboard. Use `mainKey` for residential proxies; for mobile proxies, use `mobileMainKey` and set `mealType=mobile`.
2. Choose location, quantity, protocol, output format, and session behavior using the parameters below. Preserve each query parameter's capitalization.
3. Send the request and check the HTTP status. On success, read the plain-text connection list in the selected format, then verify it in your client.

`SessionTime=0` means rotation on each request, and `SessionTime=-1` selects manual rotation. The source does not state the unit or complete supported range for positive values. Do not infer a duration from the numeric value alone.

The form's numeric bounds come from the current public interface. Country, city, and gateway line examples are not complete option lists. Use values provided by your current dashboard.

For product setup, see [dynamic residential proxies](/proxy/dynamic-residential/quick-start) or [mobile proxies](/proxy/mobile/quick-start). See [response handling](/api-reference/overview) when generation fails.

## Online debugging

<MiyaApiPlayground specUrl="/api-reference/openapi.en.json" method="GET" path="/api/ProxyLogic/Generate" locale="en" key="en:dynamic-generate" />

[Source: official dynamic generation reference](https://miyaip.com/developer-center?endpoint=dynamic-generate).


## OpenAPI

````yaml api-reference/openapi.en.json GET /api/ProxyLogic/Generate
openapi: 3.0.3
info:
  title: MiyaIP API integration
  version: '2026-10-13'
  description: >-
    This specification documents the eight endpoints published in the Developer
    Center. Response structures follow the source examples and do not claim to
    define every returned field. Form minimums, maximums, and initial values
    describe client behavior and are retained in x-miya-playground rather than
    asserted as unverified server constraints or defaults.
servers:
  - url: https://miyaip.com
    description: Production API base URL
security: []
tags:
  - name: authentication
    description: Authentication
    x-displayName: Authentication
  - name: proxy-generation
    description: Proxy generation
    x-displayName: Proxy generation
  - name: account-data
    description: Account and usage
    x-displayName: Account and usage
  - name: proxy-inventory
    description: Proxy inventory
    x-displayName: Proxy inventory
externalDocs:
  description: Developer Center source
  url: https://miyaip.com/developer-center
paths:
  /api/ProxyLogic/Generate:
    get:
      tags:
        - proxy-generation
      summary: Generate dynamic proxies
      description: >-
        Generate dynamic residential or mobile proxy credentials with optional
        location and protocol targeting.


        Crc and KeyName are query credentials. Treat both as secrets and never
        publish a generated URL.
      operationId: dynamic-generate
      parameters:
        - name: Num
          in: query
          required: true
          description: Number of proxy lines to return.
          schema:
            type: integer
            example: 1
        - name: Country
          in: query
          required: false
          description: Country code. Leave blank for a random country.
          schema:
            type: string
            example: US
        - name: State
          in: query
          required: false
          description: Optional state or province.
          schema:
            type: string
        - name: City
          in: query
          required: false
          description: Optional city.
          schema:
            type: string
        - name: SessionTime
          in: query
          required: true
          description: 0 rotates each request; -1 enables manual switching.
          schema:
            type: integer
            example: -1
        - name: Server
          in: query
          required: true
          description: Gateway node, such as as, us, or eu.
          schema:
            type: string
            example: us
        - name: Format
          in: query
          required: true
          description: Controls the returned proxy credential layout.
          schema:
            type: string
            enum:
              - '0'
              - '1'
              - '2'
            example: '0'
        - name: Crc
          in: query
          required: true
          description: Password value associated with the proxy account.
          schema:
            type: string
            format: password
        - name: Pool
          in: query
          required: true
          description: Proxy pool number.
          schema:
            type: integer
            example: 1
        - name: KeyName
          in: query
          required: true
          description: Use mainKey for residential or mobileMainKey for mobile traffic.
          schema:
            type: string
            format: password
        - name: mealType
          in: query
          required: false
          description: >-
            Use mobile for mobile traffic; leave blank for standard dynamic
            residential traffic.
          schema:
            type: string
        - name: GenType
          in: query
          required: false
          description: Optional protocol override.
          schema:
            type: string
            enum:
              - http
              - socks5
      responses:
        '200':
          description: Generated proxy lines
          content:
            text/plain:
              schema:
                type: string
              example: gateway.miyaip.com:10000:username-zone-us:********
        '400':
          description: >-
            Business or validation error


            The source labels this example as HTTP 400 while its JSON business
            code is 500. HTTP status and the JSON business code are distinct
            values; this example is not a complete catalog of error statuses or
            codes.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                  message:
                    type: string
                  body:
                    description: >-
                      The source example is null; the source does not define
                      this field's complete value type.
              example:
                code: 500
                message: Invalid request
                body: null
      security:
        - proxyCrc: []
          proxyKey: []
      externalDocs:
        description: Source reference for this endpoint
        url: https://miyaip.com/developer-center?endpoint=dynamic-generate
      x-codeSamples:
        - lang: bash
          label: cURL
          source: |-
            curl --get 'https://miyaip.com/api/ProxyLogic/Generate' \
              -H 'Accept: text/plain' \
              --data-urlencode 'Num=1' \
              --data-urlencode 'Country=US' \
              --data-urlencode 'SessionTime=-1' \
              --data-urlencode 'Server=us' \
              --data-urlencode 'Format=0' \
              --data-urlencode 'Crc=<YOUR_PASSWORD>' \
              --data-urlencode 'Pool=1' \
              --data-urlencode 'KeyName=<YOUR_MAIN_KEY>'
        - lang: javascript
          label: JavaScript
          source: |-
            const params = new URLSearchParams({
              "Num": "1",
              "Country": "US",
              "SessionTime": "-1",
              "Server": "us",
              "Format": "0",
              "Crc": "<YOUR_PASSWORD>",
              "Pool": "1",
              "KeyName": "<YOUR_MAIN_KEY>"
            });
            const url = `https://miyaip.com/api/ProxyLogic/Generate?${params}`;

            const response = await fetch(url, {
              method: 'GET',
              headers: {
                "Accept": "text/plain"
              },
            });

            const result = await response.text();
            console.log(result);
        - lang: python
          label: Python
          source: >-
            import requests


            url = "https://miyaip.com/api/ProxyLogic/Generate"

            headers = {
              "Accept": "text/plain"
            }

            params = {
              "Num": 1,
              "Country": "US",
              "SessionTime": -1,
              "Server": "us",
              "Format": "0",
              "Crc": "<YOUR_PASSWORD>",
              "Pool": 1,
              "KeyName": "<YOUR_MAIN_KEY>"
            }


            response = requests.get(url, headers=headers, params=params,
            timeout=30)

            response.raise_for_status()

            print(response.text)
components:
  securitySchemes:
    proxyCrc:
      type: apiKey
      in: query
      name: Crc
      description: >-
        Proxy-account password value; a sensitive credential in the query
        string.
    proxyKey:
      type: apiKey
      in: query
      name: KeyName
      description: Main key for the selected product; supply it together with Crc.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.