← Kembali ke blog

Cara Mengatur Proxy untuk GraphQL API: Rotasi IP dan Mengatasi Rate Limiting dengan Contoh Kode

Panduan lengkap untuk mengatur proxy untuk bekerja dengan GraphQL API: contoh kode, rotasi alamat IP, menghindari pembatasan kecepatan, dan perlindungan dari pemblokiran.

šŸ“…15 Februari 2026
```html

API GraphQL semakin populer, tetapi bersamaan dengan itu, batasan juga meningkat: batas laju, pemblokiran berdasarkan IP, filter geografis. Jika Anda bekerja dengan volume data besar melalui GraphQL — mengurai platform e-commerce, mengumpulkan analitik dari media sosial, atau menguji API — proksi adalah suatu keharusan. Dalam artikel ini, kita akan membahas cara mengatur proksi untuk permintaan GraphQL dengan benar, menerapkan rotasi IP, dan menghindari pemblokiran.

Kami akan menunjukkan contoh praktis di Python dan Node.js, membahas kesalahan umum, dan memberikan rekomendasi tentang pemilihan jenis proksi untuk berbagai tugas.

Mengapa Proksi Diperlukan untuk Permintaan GraphQL

API GraphQL sering digunakan untuk mendapatkan volume data besar dalam waktu singkat. Berbeda dengan API REST, di mana data dibagi ke dalam banyak endpoint, GraphQL memungkinkan Anda untuk meminta semua yang diperlukan dalam satu permintaan. Ini nyaman, tetapi menciptakan masalah:

  • Batas Laju — sebagian besar API GraphQL publik membatasi jumlah permintaan dari satu IP (misalnya, GitHub API: 5000 permintaan per jam, Shopify: 2 permintaan per detik)
  • Pemblokiran IP — jika melebihi batas atau aktivitas mencurigakan, IP Anda dapat diblokir selama beberapa jam atau selamanya
  • Pembatasan Geografis — beberapa API hanya tersedia dari negara tertentu (misalnya, marketplace lokal atau layanan regional)
  • Perlindungan dari Penguraian — server melacak pola permintaan dan memblokir IP yang mencurigakan

Proksi menyelesaikan masalah ini dengan memungkinkan distribusi permintaan melalui banyak alamat IP, meniru permintaan dari berbagai wilayah, dan menghindari pemblokiran. Ini sangat penting saat bekerja dengan:

  • Penguraian data dari platform e-commerce (API GraphQL Shopify, WooCommerce)
  • Pengumpulan analitik dari media sosial (API Graph Facebook, API Instagram)
  • Pemantauan harga dan ketersediaan produk
  • Pengujian API dari berbagai lokasi geografis
  • Automatisasi pengumpulan data untuk analitik dan penelitian

Jenis Proksi Apa yang Harus Dipilih untuk Bekerja dengan GraphQL

Pemilihan jenis proksi tergantung pada tugas dan persyaratan API. Mari kita bahas tiga jenis utama dan penerapannya untuk permintaan GraphQL:

Jenis Proksi Kecepatan Anonimitas Kapan Digunakan
Proksi Data Center Sangat Tinggi (10-50 ms) Sedang Penguraian API publik, pengujian, kecepatan tinggi lebih penting daripada anonimitas
Proksi Residensial Sedang (100-300 ms) Sangat Tinggi Bekerja dengan API yang dilindungi (Shopify, Facebook), menghindari filter ketat
Proksi Seluler Sedang (150-400 ms) Maksimal API Instagram, API TikTok, aplikasi seluler dengan GraphQL

Rekomendasi Pemilihan:

  • Untuk API Publik (GitHub, OpenWeather) — cukup dengan proksi data center, mereka cepat dan murah
  • Untuk e-commerce (Shopify, WooCommerce) — proksi residensial, karena platform ini aktif memfilter data center
  • Untuk Media Sosial (API Graph Facebook, Instagram) — proksi seluler atau residensial adalah suatu keharusan
  • Untuk Penguraian Massal — kombinasi: data center untuk lalu lintas utama + residensial untuk rotasi saat pemblokiran

Pengaturan Proksi di Python untuk GraphQL (requests, httpx, gql)

Python adalah salah satu bahasa paling populer untuk bekerja dengan API. Mari kita lihat tiga cara untuk mengatur proksi untuk permintaan GraphQL.

Opsi 1: Pustaka requests (klien HTTP sederhana)

Cara paling sederhana adalah menggunakan pustaka standar requests. Cocok untuk permintaan GraphQL dasar tanpa logika yang rumit.

import requests
import json

# Pengaturan proksi
proxies = {
    'http': 'http://username:password@proxy.example.com:8080',
    'https': 'http://username:password@proxy.example.com:8080'
}

# Permintaan GraphQL
query = """
query {
  products(first: 10) {
    edges {
      node {
        id
        title
        priceRange {
          minVariantPrice {
            amount
          }
        }
      }
    }
  }
}
"""

# Mengirim permintaan melalui proksi
url = "https://your-shop.myshopify.com/api/2024-01/graphql.json"
headers = {
    'Content-Type': 'application/json',
    'X-Shopify-Storefront-Access-Token': 'your_token_here',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}

response = requests.post(
    url,
    json={'query': query},
    headers=headers,
    proxies=proxies,
    timeout=30
)

data = response.json()
print(json.dumps(data, indent=2))

Opsi 2: Pustaka httpx (permintaan asinkron)

Jika perlu mengirim banyak permintaan secara paralel, gunakan httpx dengan dukungan async/await:

import httpx
import asyncio
import json

async def fetch_graphql(query, proxy_url):
    url = "https://api.example.com/graphql"
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer YOUR_TOKEN',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
    }
    
    # Pengaturan proksi untuk httpx
    proxies = {
        "http://": proxy_url,
        "https://": proxy_url
    }
    
    async with httpx.AsyncClient(proxies=proxies, timeout=30.0) as client:
        response = await client.post(
            url,
            json={'query': query},
            headers=headers
        )
        return response.json()

# Penggunaan
query = """
query {
  viewer {
    login
    repositories(first: 5) {
      nodes {
        name
        stargazerCount
      }
    }
  }
}
"""

proxy = "http://user:pass@proxy.example.com:8080"
result = asyncio.run(fetch_graphql(query, proxy))
print(json.dumps(result, indent=2))

Opsi 3: Pustaka gql (klien GraphQL khusus)

Untuk bekerja lebih lanjut dengan GraphQL, gunakan pustaka gql — mendukung validasi skema, caching, dan bekerja dengan permintaan dengan nyaman:

from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport

# Pengaturan transportasi dengan proksi
transport = RequestsHTTPTransport(
    url='https://api.example.com/graphql',
    headers={
        'Authorization': 'Bearer YOUR_TOKEN',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'
    },
    proxies={
        'http': 'http://user:pass@proxy.example.com:8080',
        'https': 'http://user:pass@proxy.example.com:8080'
    },
    timeout=30
)

# Membuat klien
client = Client(transport=transport, fetch_schema_from_transport=True)

# Permintaan GraphQL
query = gql("""
    query GetProducts($first: Int!) {
        products(first: $first) {
            edges {
                node {
                    id
                    title
                    variants(first: 1) {
                        edges {
                            node {
                                price
                            }
                        }
                    }
                }
            }
        }
    }
""")

# Melaksanakan permintaan
result = client.execute(query, variable_values={"first": 20})
print(result)

Pengaturan Proksi di Node.js untuk GraphQL (axios, apollo-client)

Node.js juga banyak digunakan untuk bekerja dengan API GraphQL. Mari kita lihat dua pendekatan utama.

Opsi 1: Axios dengan proksi

Klien HTTP yang sederhana dan fleksibel dengan dukungan proksi:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

// Pengaturan proksi
const proxyUrl = 'http://username:password@proxy.example.com:8080';
const httpsAgent = new HttpsProxyAgent(proxyUrl);

// Permintaan GraphQL
const query = `
  query {
    products(first: 10) {
      edges {
        node {
          id
          title
          priceRange {
            minVariantPrice {
              amount
            }
          }
        }
      }
    }
  }
`;

// Mengirim permintaan
axios.post('https://your-shop.myshopify.com/api/2024-01/graphql.json', 
  { query },
  {
    headers: {
      'Content-Type': 'application/json',
      'X-Shopify-Storefront-Access-Token': 'your_token_here',
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
    },
    httpsAgent: httpsAgent,
    timeout: 30000
  }
)
.then(response => {
  console.log(JSON.stringify(response.data, null, 2));
})
.catch(error => {
  console.error('Error:', error.message);
});

Opsi 2: Apollo Client dengan proksi

Apollo Client adalah klien GraphQL paling populer untuk Node.js dan browser. Pengaturan proksi melalui fetch kustom:

const { ApolloClient, InMemoryCache, HttpLink, gql } = require('@apollo/client');
const fetch = require('cross-fetch');
const HttpsProxyAgent = require('https-proxy-agent');

// Agen proksi
const proxyUrl = 'http://user:pass@proxy.example.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);

// Fetch kustom dengan proksi
const customFetch = (uri, options) => {
  return fetch(uri, {
    ...options,
    agent: agent
  });
};

// Membuat Apollo Client
const client = new ApolloClient({
  link: new HttpLink({
    uri: 'https://api.example.com/graphql',
    fetch: customFetch,
    headers: {
      'Authorization': 'Bearer YOUR_TOKEN',
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
    }
  }),
  cache: new InMemoryCache()
});

// Permintaan GraphQL
const GET_REPOS = gql`
  query GetRepositories($login: String!) {
    user(login: $login) {
      repositories(first: 5) {
        nodes {
          name
          stargazerCount
        }
      }
    }
  }
`;

// Melaksanakan permintaan
client.query({
  query: GET_REPOS,
  variables: { login: 'facebook' }
})
.then(result => {
  console.log(JSON.stringify(result.data, null, 2));
})
.catch(error => {
  console.error('Error:', error);
});

Implementasi Rotasi Proksi untuk Menghindari Batas Laju

Rotasi proksi adalah teknik kunci untuk menghindari batasan API. Alih-alih mengirim semua permintaan dari satu IP, Anda mendistribusikannya di antara banyak proksi. Ini memungkinkan Anda untuk menghindari batas laju dan menghindari pemblokiran.

Rotasi Sederhana di Python

Implementasi dasar rotasi dengan siklus pengalihan proksi:

import requests
import itertools
import time

# Daftar proksi
PROXY_LIST = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080',
    'http://user:pass@proxy4.example.com:8080',
]

# Membuat iterator tak terbatas
proxy_pool = itertools.cycle(PROXY_LIST)

def make_graphql_request(query):
    """Mengirim permintaan GraphQL dengan rotasi proksi"""
    proxy = next(proxy_pool)
    proxies = {'http': proxy, 'https': proxy}
    
    url = "https://api.example.com/graphql"
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer YOUR_TOKEN',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
    }
    
    try:
        response = requests.post(
            url,
            json={'query': query},
            headers=headers,
            proxies=proxies,
            timeout=30
        )
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"Error with proxy {proxy}: {e}")
        # Beralih ke proksi berikutnya
        return make_graphql_request(query)

# Contoh penggunaan
queries = [
    'query { products(first: 10) { edges { node { id title } } } }',
    'query { collections(first: 5) { edges { node { id title } } } }',
    'query { shop { name email } }'
]

for query in queries:
    result = make_graphql_request(query)
    print(result)
    time.sleep(1)  # Jeda antara permintaan

Rotasi Cerdas dengan Pelacakan Kesalahan

Versi yang lebih canggih, yang melacak proksi yang tidak berfungsi dan secara otomatis mengecualikannya dari kolam:

import requests
import random
from collections import defaultdict
import time

class ProxyRotator:
    def __init__(self, proxy_list, max_failures=3):
        self.proxy_list = proxy_list.copy()
        self.max_failures = max_failures
        self.failures = defaultdict(int)
        self.active_proxies = proxy_list.copy()
    
    def get_proxy(self):
        """Mendapatkan proksi aktif secara acak"""
        if not self.active_proxies:
            raise Exception("Semua proksi tidak tersedia!")
        return random.choice(self.active_proxies)
    
    def mark_failure(self, proxy):
        """Menandai percobaan yang gagal"""
        self.failures[proxy] += 1
        if self.failures[proxy] >= self.max_failures:
            print(f"Proksi {proxy} dikeluarkan dari kolam (melebihi batas kesalahan)")
            if proxy in self.active_proxies:
                self.active_proxies.remove(proxy)
    
    def mark_success(self, proxy):
        """Mengatur ulang penghitung kesalahan saat berhasil"""
        self.failures[proxy] = 0

# Inisialisasi
proxies = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080',
]

rotator = ProxyRotator(proxies)

def graphql_request_with_retry(query, max_retries=3):
    """Permintaan GraphQL dengan pengulangan otomatis"""
    for attempt in range(max_retries):
        proxy = rotator.get_proxy()
        proxies_dict = {'http': proxy, 'https': proxy}
        
        try:
            response = requests.post(
                'https://api.example.com/graphql',
                json={'query': query},
                headers={
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer TOKEN',
                    'User-Agent': 'Mozilla/5.0'
                },
                proxies=proxies_dict,
                timeout=30
            )
            response.raise_for_status()
            
            # Sukses — reset penghitung kesalahan
            rotator.mark_success(proxy)
            return response.json()
            
        except Exception as e:
            print(f"Percobaan {attempt + 1}/{max_retries} dengan {proxy} gagal: {e}")
            rotator.mark_failure(proxy)
            time.sleep(2)  # Jeda sebelum pengulangan
    
    raise Exception("Tidak dapat melakukan permintaan setelah semua percobaan")

# Penggunaan
query = 'query { products(first: 10) { edges { node { id title } } } }'
result = graphql_request_with_retry(query)
print(result)

Pengaturan Header dan User-Agent untuk Permintaan GraphQL

Header HTTP yang benar sangat penting untuk keberhasilan bekerja dengan API GraphQL melalui proksi. Banyak API memeriksa tidak hanya IP, tetapi juga header permintaan.

Header Wajib untuk GraphQL

headers = {
    # Jenis konten — selalu application/json untuk GraphQL
    'Content-Type': 'application/json',
    
    # Otorisasi (tergantung pada API)
    'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
    # atau
    'X-Shopify-Storefront-Access-Token': 'token_here',
    
    # User-Agent — meniru browser nyata
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    
    # Accept — menunjukkan bahwa kita menerima JSON
    'Accept': 'application/json',
    
    # Accept-Language — bahasa pengguna
    'Accept-Language': 'en-US,en;q=0.9',
    
    # Accept-Encoding — dukungan kompresi
    'Accept-Encoding': 'gzip, deflate, br',
    
    # Referer — dari mana permintaan berasal (opsional)
    'Referer': 'https://example.com/',
    
    # Origin — untuk permintaan CORS
    'Origin': 'https://example.com'
}

Rotasi User-Agent

Untuk lebih banyak anonimitas, disarankan untuk merotasi User-Agent bersamaan dengan proksi:

import random

USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15'
]

def get_random_headers(token):
    """Menghasilkan header acak"""
    return {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {token}',
        'User-Agent': random.choice(USER_AGENTS),
        'Accept': 'application/json',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br'
    }

Penanganan Kesalahan dan Pengulangan Melalui Proksi

Saat bekerja dengan proksi, kesalahan tidak dapat dihindari: timeout, proksi tidak tersedia, pemblokiran. Penting untuk menangani situasi ini dengan benar dan menerapkan mekanisme pengulangan.

Kesalahan Umum GraphQL melalui Proksi

  • Timeout — proksi lambat atau terbebani (tingkatkan timeout menjadi 30-60 detik)
  • HTTP 407 Proxy Authentication Required — login/password proksi tidak valid
  • HTTP 429 Too Many Requests — melebihi batas laju (perlu rotasi proksi)
  • HTTP 403 Forbidden — IP proksi diblokir (ganti jenis proksi ke residensial)
  • Connection refused — proksi tidak tersedia (kecualikan dari kolam)

Penanganan Kesalahan yang Canggih

import requests
import time
from requests.exceptions import ProxyError, Timeout, ConnectionError

def graphql_request_robust(query, proxy, max_retries=3, backoff=2):
    """
    Permintaan GraphQL yang andal dengan penanganan semua jenis kesalahan
    
    Args:
        query: Permintaan GraphQL
        proxy: URL proksi
        max_retries: maksimum percobaan
        backoff: pengali jeda antara percobaan
    """
    url = "https://api.example.com/graphql"
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer TOKEN',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
    }
    proxies = {'http': proxy, 'https': proxy}
    
    for attempt in range(max_retries):
        try:
            response = requests.post(
                url,
                json={'query': query},
                headers=headers,
                proxies=proxies,
                timeout=30
            )
            
            # Memeriksa batas laju
            if response.status_code == 429:
                retry_after = int(response.headers.get('Retry-After', 60))
                print(f"Batas laju! Menunggu {retry_after} detik...")
                time.sleep(retry_after)
                continue
            
            # Memeriksa pemblokiran IP
            if response.status_code == 403:
                print(f"IP {proxy} diblokir! Perlu proksi lain.")
                raise Exception("IP diblokir")
            
            # Memeriksa kesalahan otorisasi proksi
            if response.status_code == 407:
                print(f"Kesalahan otorisasi proksi {proxy}")
                raise Exception("Otorisasi proksi gagal")
            
            response.raise_for_status()
            
            # Memeriksa kesalahan GraphQL
            data = response.json()
            if 'errors' in data:
                print(f"Kesalahan GraphQL: {data['errors']}")
                # Beberapa kesalahan bisa diulang, beberapa tidak
                if is_retryable_graphql_error(data['errors']):
                    time.sleep(backoff * (attempt + 1))
                    continue
                else:
                    raise Exception(f"Kesalahan GraphQL: {data['errors']}")
            
            return data
            
        except (ProxyError, ConnectionError) as e:
            print(f"Percobaan {attempt + 1}: Proksi tidak tersedia - {e}")
            time.sleep(backoff * (attempt + 1))
            
        except Timeout as e:
            print(f"Percobaan {attempt + 1}: Timeout - {e}")
            time.sleep(backoff * (attempt + 1))
            
        except requests.exceptions.HTTPError as e:
            print(f"Percobaan {attempt + 1}: Kesalahan HTTP - {e}")
            if attempt < max_retries - 1:
                time.sleep(backoff * (attempt + 1))
            else:
                raise
    
    raise Exception(f"Tidak dapat melakukan permintaan setelah {max_retries} percobaan")

def is_retryable_graphql_error(errors):
    """Menentukan apakah permintaan dapat diulang pada kesalahan GraphQL"""
    retryable_codes = ['THROTTLED', 'INTERNAL_ERROR', 'TIMEOUT']
    for error in errors:
        if error.get('extensions', {}).get('code') in retryable_codes:
            return True
    return False

Praktik Terbaik Bekerja dengan GraphQL Melalui Proksi

Mari kita ringkas dan memberikan rekomendasi untuk bekerja secara efektif dengan API GraphQL melalui proksi:

āœ“ Optimisasi Permintaan

  • Mintalah hanya bidang yang diperlukan — GraphQL memungkinkan Anda untuk secara tepat menentukan apa yang diperlukan
  • Gunakan paginasi daripada meminta semua data sekaligus
  • Kelompokkan permintaan terkait dalam satu (GraphQL mendukung permintaan ganda)
  • Cache hasil di sisi klien untuk mengurangi jumlah permintaan

āœ“ Manajemen Proksi

  • Gunakan kolam minimal 5-10 proksi untuk rotasi
  • Secara teratur periksa keandalan proksi (health check)
  • Secara otomatis kecualikan proksi yang tidak berfungsi dari kolam
  • Untuk tugas kritis, simpan proksi cadangan dari jenis lain

āœ“ Mematuhi Batasan

  • Pelajari dokumentasi API — di sana tercantum batasan yang tepat
  • Tambahkan jeda antara permintaan (1-2 detik minimal)
  • Pantau header X-RateLimit-Remaining dan X-RateLimit-Reset
  • Ketika menerima kesalahan 429, tingkatkan jeda secara eksponensial

āœ“ Keamanan dan Anonimitas

  • Selalu gunakan proksi HTTPS untuk melindungi token otorisasi
  • Rotasi User-Agent bersamaan dengan proksi
  • Jangan simpan token dalam kode — gunakan variabel lingkungan
  • Catat hanya informasi yang diperlukan

Arsitektur yang Direkomendasikan untuk Proyek Skala Besar

Jika Anda bekerja dengan volume data besar, kami merekomendasikan arsitektur berikut:

  1. Antrian Tugas (Redis, RabbitMQ) — untuk mendistribusikan permintaan di antara pekerja
  2. Kolam Pekerja — setiap pekerja menggunakan proksi mereka sendiri
  3. Manajer Proksi — melacak status proksi dan mendistribusikannya di antara pekerja
  4. Basis Data — untuk menyimpan hasil dan status tugas
  5. Pemantauan — melacak kesalahan, kecepatan, penggunaan proksi

Kesimpulan

Bekerja dengan API GraphQL melalui proksi bukan hanya menambahkan parameter proxies dalam permintaan. Untuk bekerja yang andal dan efektif, Anda perlu menerapkan rotasi proksi, penanganan kesalahan yang benar, mengatur header, dan mematuhi batasan API. Kami telah membahas contoh praktis di Python dan Node.js yang dapat langsung digunakan dalam proyek Anda.

Kesimpulan utama: gunakan proksi residensial untuk API yang dilindungi (Shopify, Facebook), data center untuk API publik dan penguraian massal, terapkan rotasi otomatis dengan pengecualian proksi yang tidak berfungsi, tambahkan jeda dan tangani semua jenis kesalahan. Ini akan memungkinkan Anda untuk bekerja dengan stabil dengan semua API GraphQL tanpa pemblokiran.

Jika Anda berencana untuk bekerja dengan API GraphQL dalam produksi, kami merekomendasikan menggunakan proksi residensial — mereka memberikan stabilitas maksimum dan risiko pemblokiran minimal. Untuk pengujian dan pengembangan, proksi data center sudah cukup — mereka lebih cepat dan lebih murah.

```