μ€μκ°μΌλ‘ μμ§Β·κ²μ¦λ λ¬΄λ£ νλ‘μ λͺ©λ‘μ κ°μ Έλ€ μ°κΈ° μν REST API. λͺ¨λ μλν¬μΈνΈλ μΈμ¦ μμ΄ μ¬μ©νλ€.
https://proxy.gulu.krContent-Type: application/json)YYYY-MM-DD HH:MM:SS)μ΄ λ¬Έμμ λͺ¨λ URLΒ·μλ΅Β·μμ λ μ€μ μλ²μ λν΄ κ²μ¦λ κ²μ΄λ€(2026-06-18).
# 1) λ°λ‘ μΈ μ μλ(usable) νλ‘μλ₯Ό μ§μ°μκ° λΉ λ₯Έ μμΌλ‘ κ°μ Έμ€κΈ°
curl 'https://proxy.gulu.kr/api/proxies?status=usable&sort=latency&limit=20'
# 2) λ°μ λͺ©λ‘μμ νλ κ³¨λΌ μ€μ λ‘ μ¬μ© (socks5 μμ)
curl --socks5-hostname 49.143.59.205:110 https://api.ipify.org
# -> 49.143.59.205 (νλ‘μμ IPκ° μΆλ ₯λλ©΄ μ μ λμ)
status=usableμ μ¦μ μ¬μ© κ°λ₯ν νλ‘μλ§ μ€λ€(μλ "usable κ·μΉ" μ°Έμ‘°). κ°μ₯ νν μ¬μ© ν¨ν΄μ΄λ€.
GET /api/proxies β νλ‘μ λͺ©λ‘κ°μ₯ ν΅μ¬ μλν¬μΈνΈ. νν°Β·μ λ ¬Β·νμ΄μ§λ€μ΄μ μ μ§μνλ€.
쿼리 νλΌλ―Έν° (λͺ¨λ μ ν)
| μ΄λ¦ | κ° | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|
status |
usable | alive | all |
usable |
usable=λ°λ‘ μ¬μ© κ°λ₯, alive=λ§μ§λ§ κ²μ¬μμ μ΄μμμ, all=μ 체 |
protocol |
http | socks5 |
(μ 체) | νλ‘ν μ½ νν° |
country |
κ΅κ°μ½λ (μ: KR, US) |
(μ 체) | ISO 2μ리, λμλ¬Έμ λ¬΄κ΄ |
anonymity |
elite | anonymous | transparent |
(μ 체) | μ΅λͺ λ |
https |
1 | true | yes |
(무κ΄) | HTTPS(CONNECT) ν°λλ§ μ§μλ§ |
max_latency |
μ μ(ms) | (무μ ν) | μ΄ μ§μ°μκ° μ΄νλ§ |
sort |
latency | checked | country | uptime |
latency |
μ λ ¬ κΈ°μ€ |
limit |
μ μ (μ΅λ 2000) | 200 |
νμ΄μ§ ν¬κΈ° |
offset |
μ μ | 0 |
νμ΄μ§ μ€νμ |
μλͺ»λ κ°μ HTTP
422λ‘ κ±°λΆλλ€(μ:status=bogus,limit=abc).
μμ URL
https://proxy.gulu.kr/api/proxies?status=usable&sort=latency&limit=20
https://proxy.gulu.kr/api/proxies?status=usable&protocol=socks5&country=KR
https://proxy.gulu.kr/api/proxies?status=alive&protocol=http&https=1&anonymity=elite
https://proxy.gulu.kr/api/proxies?status=usable&sort=uptime&max_latency=1000
https://proxy.gulu.kr/api/proxies?status=alive&limit=100&offset=100
μλ΅ (μ€μ μμ)
{
"count": 3,
"total": 8,
"offset": 0,
"proxies": [
{
"ip": "49.143.59.205",
"port": 110,
"protocol": "socks5",
"country": "South Korea",
"country_code": "KR",
"anonymity": "unknown",
"https": 1,
"latency_ms": 119,
"alive": 1,
"usable": 1,
"sources": "proxyscrape,proxyscrape-api-v4,stormsia-proxy-list-socks5,...",
"last_checked": "2026-06-18 12:02:40",
"last_alive": "2026-06-18 12:02:40",
"check_count": 1,
"success_count": 1,
"checked_age_s": 334,
"alive_age_s": 334
}
]
}
νλ μ€λͺ
| νλ | μ€λͺ |
|---|---|
ip, port, protocol |
μ μ μ 보 (http λλ socks5) |
country, country_code |
μΆκ΅¬(exit) κ΅κ° |
anonymity |
elite(IPΒ·νλ‘μ νμ λͺ¨λ μ¨κΉ) / anonymous(νλ‘μ νμ λ
ΈμΆ) / transparent(μ€ IP λ
ΈμΆ) / unknown |
https |
1μ΄λ©΄ HTTPS(CONNECT) ν°λλ§ μ§μ β HTTPS μ¬μ΄νΈμ μ¬μ© κ°λ₯ |
latency_ms |
λ§μ§λ§ κ²μ¬ μ μλ΅ μ§μ°(ms) |
alive |
λ§μ§λ§ κ²μ¬μμ μ΄μμμλμ§ (1/0) |
usable |
"λ°λ‘ μΈ μ μμ" νλκ·Έ (μλ κ·μΉ) |
sources |
μ΄ νλ‘μλ₯Ό λ³΄κ³ ν μμ€ μ΄λ¦(μ½€λ§ κ΅¬λΆ) |
last_checked, last_alive |
λ§μ§λ§ κ²μ¬ / λ§μ§λ§ μμ‘΄ μκ° (UTC) |
check_count, success_count |
λμ κ²μ¬/μ±κ³΅ νμ (κ°λλ₯ κ³μ°μ©) |
checked_age_s, alive_age_s |
λ§μ§λ§ κ²μ¬/μμ‘΄ μ΄ν κ²½κ³Ό μ΄ (μλ²κ° UTCλ‘ κ³μ°ν΄ λ΄λ €μ€ β μ μ λ νλ¨μ μ¬μ©) |
μλ΅ μ΅μμμ count=μ΄λ² νμ΄μ§ ν μ, total=νν° μΌμΉ μ΄ κ°μ, offset=μμ² μ€νμ
.
GET /api/stats β μμ½ ν΅κ³https://proxy.gulu.kr/api/stats
{
"total": 515399,
"alive": 40,
"usable": 9,
"checked": 172247,
"by_protocol": { "socks5": 9 },
"by_anonymity": { "elite": 5, "unknown": 35 },
"last_check_at": "2026-06-18 12:07:13"
}
by_protocolμ usable κΈ°μ€, by_anonymityλ alive κΈ°μ€ μ§κ³.
GET /api/countries β κ΅κ° λͺ©λ‘usable νλ‘μκ° μλ κ΅κ°λ₯Ό 건μ λ΄λ¦Όμ°¨μμΌλ‘.
https://proxy.gulu.kr/api/countries
[
{ "country_code": "JP", "country": "Japan", "c": 2 },
{ "country_code": "KR", "country": "South Korea", "c": 2 },
{ "country_code": "SG", "country": "Singapore", "c": 2 }
]
GET /api/sources β μμ€λ³ κΈ°μ¬ νν©λ±λ‘λ μ½ 244κ° μμ€μ κ° μμ€κ° κΈ°μ¬ν νλ‘μ μ(30μ΄ μΊμ).
https://proxy.gulu.kr/api/sources
{
"count": 244,
"enabled": 229,
"sources": [
{
"name": "vmheaven-vmheaven-io-free-proxy-list",
"kind": "text",
"reliability": "medium",
"enabled": true,
"protocols": ["http", "socks5"],
"note": "vmheaven/vmheaven.io-free-proxy-list (GitHub raw)",
"urls": ["https://raw.githubusercontent.com/.../http.txt", "..."],
"total": 6311,
"alive": 8,
"usable": 5
}
]
}
usable/alive/total λ΄λ¦Όμ°¨μ μ λ ¬.
POST /api/collect β μλ μμ§ νΈλ¦¬κ±° (κ΄λ¦¬μ©)λͺ¨λ μμ€λ₯Ό μ¦μ 1ν μ¬μμ§νλ€. λ°±κ·ΈλΌμ΄λκ° 30λΆλ§λ€ μλ μννλ―λ‘ λ³΄ν΅μ νμ μλ€. μλ£κΉμ§ μ½ 1λΆ λΈλ‘λλ©° μμ½μ λ°ννλ€.
curl -X POST https://proxy.gulu.kr/api/collect
{ "total_unique": 507742, "sources_ok": 222, "per_source": { "fyvri-fresh-proxy-list": 453414, "...": 0 } }
APIμμ λ°μ νλ‘μλ₯Ό μ€μ λ‘ μ°λ λ°©λ². 49.143.59.205:110(socks5, KR)λ‘ μ€μΈ‘ κ²μ¦λ¨ β νλ‘μ κ²½μ μ exit IPκ° νλ‘μ IPλ‘ λ°λλ€.
# socks5 (DNSλ νλ‘μμμ ν΄μ: --socks5-hostname)
curl --socks5-hostname 49.143.59.205:110 https://api.ipify.org # -> 49.143.59.205
# http νλ‘μ
curl -x http://IP:PORT https://api.ipify.org
pip install "requests[socks]")import requests
# 1) usable νλ‘μλ€μ λ°μ μ΄μμλ κ²μ λ§λ λκΉμ§ μλ(λ¬΄λ£ νλ‘μλ μμ£Ό μ£½μΌλ―λ‘ ν΄λ°± νμ)
proxies = requests.get("https://proxy.gulu.kr/api/proxies",
params={"status": "usable", "sort": "latency", "limit": 20}).json()["proxies"]
for p in proxies:
scheme = "socks5h" if p["protocol"] == "socks5" else "http"
proxy_url = f"{scheme}://{p['ip']}:{p['port']}"
try:
r = requests.get("https://api.ipify.org",
proxies={"http": proxy_url, "https": proxy_url}, timeout=15)
print("exit ip:", r.text) # νλ‘μμ IPκ° λμ€λ©΄ μ±κ³΅
break
except Exception:
continue # λ€μ νλ‘μλ‘ ν΄λ°±
npm i socks-proxy-agent) β μ€μΈ‘ κ²μ¦λ ν¨ν΄import https from 'node:https';
import { SocksProxyAgent } from 'socks-proxy-agent';
const list = await (await fetch(
'https://proxy.gulu.kr/api/proxies?status=usable&protocol=socks5&sort=latency&limit=20'
)).json();
for (const p of list.proxies) {
const agent = new SocksProxyAgent(`socks5h://${p.ip}:${p.port}`, { timeout: 8000 });
const exitIp = await new Promise((resolve) => {
const req = https.request({ hostname: 'api.ipify.org', path: '/', agent, timeout: 10000 },
(r) => { let d = ''; r.on('data', (c) => d += c); r.on('end', () => resolve(d.trim())); });
req.on('error', () => resolve(null));
req.on('timeout', () => { req.destroy(); resolve(null); });
req.end();
});
agent.destroy();
if (exitIp) { console.log('exit ip:', exitIp); break; } // μ±κ³΅ β μ¬μ©; μ€ν¨ μ λ€μ νλ‘μλ‘ ν΄λ°±
}
status=usableλ₯Ό κΈ°λ³ΈμΌλ‘ μ¬μ©νλ€. socks5λ μ΄μμμΌλ©΄ usable, httpλ elite + httpsκΉμ§ λ§μ‘±ν΄μΌ usableμ΄λ€.checked_age_sκ° μμ(μ: < 600μ΄) νλ‘μλ₯Ό μ°μ μ¬μ©νλ€. λ¬΄λ£ νλ‘μλ μλͺ
μ΄ μ§§λ€.limitμ λλν). κ°λ³ νλ‘μλ μΈμ λ μ£½μ μ μμΌλ μ€ν¨ μ λ€μ κ²μΌλ‘ ν΄λ°±νλ€.https=1λ‘ νν°νκ±°λ https νλκ° 1μΈ κ²μ μ΄λ€.usable κ·μΉusable = (protocol == "socks5" && alive)
|| (protocol == "http" && alive && anonymity == "elite" && https)
| μν© | μλ΅ |
|---|---|
μλͺ»λ status |
`422 {"detail":"status must be one of usable |
limit/offset/max_latency κ° μ μ μλ |
422 {"detail":"... must be an integer"} |