Jika Anda menulis parser, mengintegrasikan API eksternal, atau mengotomatiskan pengumpulan data di Ruby — cepat atau lambat Anda akan menghadapi pemblokiran berdasarkan IP. Wildberries, Ozon, Instagram, dan puluhan layanan lainnya memotong permintaan dari satu alamat setelah beberapa ratus permintaan. Solusinya adalah satu — proxy. Dalam artikel ini, kita akan membahas cara menghubungkan proxy ke proyek Ruby melalui Net::HTTP standar dan klien HTTP populer Faraday, mengatur rotasi IP dan menangani kesalahan dengan benar — baik dalam aplikasi Rails maupun dalam skrip sederhana.
Mengapa Pengembang Ruby Membutuhkan Proxy: Skenario Utama
Ruby banyak digunakan untuk tugas-tugas di mana tanpa proxy tidak mungkin dilakukan. Sebelum beralih ke kode, penting untuk memahami dalam situasi apa mereka dibutuhkan — ini akan membantu memilih jenis dan arsitektur solusi yang tepat.
Pemrosesan dan Pengumpulan Data. Ini adalah skenario yang paling umum. Anda menulis skrip di Ruby yang mengunjungi halaman Wildberries, Ozon, atau Avito, mengumpulkan harga dan spesifikasi produk. Tanpa proxy, skrip semacam itu akan diblokir berdasarkan IP dalam beberapa menit. Situs web melihat ratusan permintaan dari satu alamat dan secara otomatis mengaktifkan perlindungan — captcha, larangan sementara, atau penolakan layanan sepenuhnya.
Integrasi dengan API yang Bergantung pada Geolokasi. Beberapa layanan eksternal mengembalikan konten yang berbeda tergantung pada negara permintaan. Jika aplikasi Rails Anda mengakses API semacam itu, proxy memungkinkan untuk meniru permintaan dari wilayah yang diperlukan. Misalnya, memeriksa hasil pencarian untuk berbagai negara atau mendapatkan harga yang relevan untuk pasar tertentu.
Pemrograman dan QA. Pengembang menggunakan proxy untuk menguji perilaku aplikasi saat permintaan datang dari berbagai alamat IP dan negara. Ini sangat relevan untuk layanan dengan pemblokiran geolokasi atau pembatasan berdasarkan IP.
Automatisasi Pemasaran. Skrip Ruby sering digunakan untuk memantau kampanye iklan, memeriksa posisi dalam hasil pencarian, atau melacak aktivitas pesaing. Di sini proxy diperlukan untuk mendistribusikan beban dan menghindari batasan.
Kerja dengan Beberapa Akun. Jika skrip Anda mengelola beberapa akun di satu platform, setiap akun harus beroperasi melalui IP yang terpisah — jika tidak, platform dapat dengan mudah mendeteksi hubungan dan memblokir semuanya sekaligus.
Jenis Proxy Apa yang Harus Dipilih untuk Tugas Ruby
Tidak semua proxy cocok untuk berbagai tugas. Pemilihan jenis secara langsung mempengaruhi keberhasilan skrip Anda. Mari kita bahas opsi utama yang relevan dengan pengembangan Ruby.
| Jenis Proxy | Tugas Terbaik di Ruby | Kecepatan | Menghindari Perlindungan |
|---|---|---|---|
| Proxy Data Center | Pemrosesan tanpa perlindungan ketat, permintaan API, pengujian | Tinggi | Sedang |
| Proxy Residensial | Pemrosesan situs yang dilindungi, bekerja dengan media sosial, marketplace | Sedang | Tinggi |
| Proxy Seluler | Facebook, Instagram, TikTok API, bekerja dengan akun | Sedang | Maksimal |
Proxy Data Center — adalah opsi tercepat dan termurah. Cocok untuk pemrosesan situs tanpa perlindungan agresif, permintaan API massal, dan pengujian beban. Namun, platform besar (Facebook, Google, Cloudflare) dengan mudah mengenali mereka berdasarkan ASN data center.
Proxy Residensial menggunakan IP pengguna rumah nyata. Untuk skrip Ruby yang memproses Wildberries, Ozon, atau bekerja dengan situs yang dilindungi — ini adalah pilihan optimal. Situs web melihat pengguna biasa, bukan server.
Proxy Seluler beroperasi melalui IP operator seluler (4G/5G). Ini adalah alamat yang paling dipercaya dari sudut pandang platform — satu IP seluler dapat digunakan oleh ratusan pengguna nyata secara bersamaan, sehingga pemblokiran sangat jarang terjadi. Jika skrip Ruby Anda bekerja dengan media sosial atau platform iklan — proxy seluler akan mengurangi risiko pemblokiran hingga minimum.
Proxy di Net::HTTP: Pengaturan Dasar
Net::HTTP — adalah pustaka standar Ruby untuk permintaan HTTP, yang termasuk dalam distribusi standar bahasa. Ini mendukung proxy "out of the box" melalui metode khusus Net::HTTP::Proxy.
Cara paling sederhana adalah membuat kelas proxy dan menggunakannya sebagai pengganti Net::HTTP biasa:
require 'net/http'
require 'uri'
# Data proxy
proxy_host = 'proxy.example.com'
proxy_port = 8080
# Membuat kelas proxy
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port)
# Melakukan permintaan melalui proxy
uri = URI('https://httpbin.org/ip')
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.body
end
Metode Net::HTTP::Proxy menerima empat parameter: host proxy, port, nama pengguna, dan kata sandi. Dua yang pertama wajib, dua yang terakhir opsional untuk proxy tanpa autentikasi.
Cara alternatif adalah dengan mengirimkan parameter proxy langsung ke metode Net::HTTP.new:
require 'net/http'
uri = URI('https://httpbin.org/ip')
http = Net::HTTP.new(
uri.host,
uri.port,
'proxy.example.com', # proxy_addr
8080, # proxy_port
nil, # proxy_user (nil jika tanpa autentikasi)
nil # proxy_pass
)
http.use_ssl = true
response = http.get(uri.path)
puts response.body
Pendekatan ini nyaman ketika Anda perlu menggunakan objek HTTP yang sama untuk beberapa permintaan ke satu host. Perhatikan: parameter proxy dikirimkan sebagai argumen ketiga dan keempat, bukan melalui metode terpisah.
Autentikasi dan HTTPS melalui Net::HTTP
Sebagian besar proxy komersial memerlukan autentikasi — login dan kata sandi. Selain itu, saat bekerja dengan situs HTTPS, diperlukan pengaturan SSL tambahan. Mari kita bahas kedua kasus tersebut.
Proxy dengan login dan kata sandi:
require 'net/http'
require 'uri'
proxy_host = 'proxy.example.com'
proxy_port = 8080
proxy_user = 'your_username'
proxy_pass = 'your_password'
# Membuat kelas proxy dengan autentikasi
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass)
uri = URI('https://httpbin.org/ip')
proxy_class.start(uri.host, uri.port, use_ssl: true) do |http|
# Nonaktifkan verifikasi SSL (hanya untuk pengujian!)
# http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
response = http.request(request)
puts "IP: #{response.body}"
puts "Status: #{response.code}"
end
Poin penting: saat menggunakan proxy HTTPS (tunneling melalui CONNECT) Net::HTTP secara otomatis membuat koneksi SSL ke server tujuan melalui tunnel proxy. Ini bekerja dengan benar untuk sebagian besar server proxy.
Pengaturan melalui variabel lingkungan. Praktik yang baik adalah tidak menghardcode data proxy dalam kode, tetapi membacanya dari variabel lingkungan:
require 'net/http'
require 'uri'
# Membaca pengaturan proxy dari ENV
proxy_uri = URI(ENV.fetch('HTTP_PROXY', 'http://proxy.example.com:8080'))
proxy_class = Net::HTTP::Proxy(
proxy_uri.host,
proxy_uri.port,
proxy_uri.user,
proxy_uri.password
)
target_uri = URI('https://httpbin.org/ip')
proxy_class.start(target_uri.host, target_uri.port, use_ssl: true) do |http|
response = http.get(target_uri.path)
puts response.body
end
Variabel lingkungan dapat ditetapkan dalam format HTTP_PROXY=http://user:[email protected]:8080. Pendekatan ini memungkinkan untuk mengubah proxy tanpa mengubah kode — cukup perbarui variabel di file .env atau di pengaturan server.
Menghubungkan Proxy melalui Faraday
Faraday — salah satu klien HTTP paling populer dalam ekosistem Ruby. Ini digunakan dalam banyak aplikasi Rails berkat pendekatan middleware yang nyaman dan dukungan untuk berbagai adapter (Net::HTTP, HTTParty, Typhoeus, dan lainnya). Pengaturan proxy di Faraday sedikit berbeda tergantung pada adapter yang digunakan.
Pengaturan dasar proxy di Faraday:
require 'faraday'
# Membuat koneksi Faraday dengan proxy
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = {
uri: 'http://proxy.example.com:8080',
user: 'your_username',
password: 'your_password'
}
faraday.headers['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
faraday.adapter Faraday.default_adapter
end
response = conn.get('/ip')
puts response.body
puts "Status: #{response.status}"
Parameter faraday.proxy menerima hash dengan kunci uri, user, dan password. Anda juga dapat mengirimkan string URI langsung jika proxy tidak memerlukan autentikasi.
Faraday dengan adapter Net::HTTP dan pengaturan lanjutan:
require 'faraday'
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = 'http://user:[email protected]:8080'
# Pengaturan timeout
faraday.options.timeout = 30
faraday.options.open_timeout = 10
# Middleware untuk logging (berguna saat debugging)
faraday.response :logger
# Retry saat terjadi kesalahan koneksi
faraday.request :retry, max: 3, interval: 1
# Adapter
faraday.adapter :net_http
end
begin
response = conn.get('/ip')
puts response.body
rescue Faraday::ConnectionFailed => e
puts "Kesalahan koneksi: #{e.message}"
rescue Faraday::TimeoutError => e
puts "Timeout: #{e.message}"
end
Middleware :retry sangat berguna saat bekerja dengan proxy — jika satu alamat tidak tersedia sementara, Faraday secara otomatis akan mengulangi permintaan. Ini sangat penting untuk memastikan skrip berfungsi dengan baik di produksi.
Faraday dengan adapter Typhoeus (untuk permintaan paralel):
# Gemfile: gem 'typhoeus'
require 'faraday'
require 'typhoeus/adapters/faraday'
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.proxy = 'http://user:[email protected]:8080'
faraday.adapter :typhoeus
end
# Permintaan paralel melalui proxy
responses = []
conn.in_parallel do
responses << conn.get('/ip')
responses << conn.get('/headers')
responses << conn.get('/user-agent')
end
responses.each { |r| puts r.body }
Rotasi Proxy: Perubahan IP Otomatis
Satu alamat proxy, bahkan yang residensial, cepat atau lambat akan terkena batasan saat pemrosesan intensif. Solusinya adalah rotasi: perubahan IP otomatis setelah setiap permintaan atau melalui interval tertentu. Mari kita implementasikan rotator sederhana untuk skrip Ruby.
Rotator sederhana berdasarkan array proxy:
require 'net/http'
require 'uri'
class ProxyRotator
def initialize(proxies)
@proxies = proxies
@index = 0
@mutex = Mutex.new
end
def next_proxy
@mutex.synchronize do
proxy = @proxies[@index % @proxies.length]
@index += 1
proxy
end
end
def random_proxy
@proxies.sample
end
end
# Daftar proxy dalam format [host, port, user, pass]
proxies = [
['proxy1.example.com', 8080, 'user1', 'pass1'],
['proxy2.example.com', 8080, 'user2', 'pass2'],
['proxy3.example.com', 8080, 'user3', 'pass3'],
]
rotator = ProxyRotator.new(proxies)
# Memproses daftar URL melalui berbagai proxy
urls = [
'https://httpbin.org/ip',
'https://httpbin.org/headers',
'https://httpbin.org/user-agent'
]
urls.each do |url|
proxy = rotator.next_proxy
proxy_class = Net::HTTP::Proxy(proxy[0], proxy[1], proxy[2], proxy[3])
uri = URI(url)
begin
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.read_timeout = 15
response = http.get(uri.path)
puts "#{url} -> Status: #{response.code}, Proxy: #{proxy[0]}"
end
rescue => e
puts "Kesalahan dengan proxy #{proxy[0]}: #{e.message}"
# Beralih ke proxy berikutnya secara otomatis
end
sleep(rand(0.5..2.0)) # Penundaan acak antara permintaan
end
Penundaan acak antara permintaan (sleep(rand(0.5..2.0))) — adalah elemen penting. Pola permintaan dengan interval tetap mudah terdeteksi oleh sistem anti-bot. Penundaan acak meniru perilaku pengguna nyata.
Rotasi melalui Faraday dengan middleware:
require 'faraday'
class ProxyMiddleware < Faraday::Middleware
PROXIES = [
'http://user1:[email protected]:8080',
'http://user2:[email protected]:8080',
'http://user3:[email protected]:8080',
].freeze
def call(env)
# Memilih proxy acak untuk setiap permintaan
proxy_uri = URI(PROXIES.sample)
env[:request][:proxy] = {
uri: proxy_uri,
user: proxy_uri.user,
password: proxy_uri.password
}
@app.call(env)
end
end
# Mendaftarkan middleware
Faraday::Middleware.register_middleware proxy_rotator: ProxyMiddleware
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
faraday.use :proxy_rotator
faraday.adapter :net_http
end
5.times do
response = conn.get('/ip')
puts response.body
end
Integrasi Proxy dalam Aplikasi Rails
Dalam aplikasi Rails, proxy sering kali diperlukan untuk permintaan HTTP eksternal: integrasi dengan API, tugas pemrosesan latar belakang, atau webhook. Mari kita lihat beberapa pola praktis.
Pola 1: Objek Layanan dengan Faraday. Membuat kelas layanan dasar yang melakukan semua permintaan HTTP eksternal melalui proxy:
# app/services/http_client.rb
class HttpClient
def self.connection(base_url)
Faraday.new(url: base_url) do |faraday|
# Proxy dari variabel lingkungan Rails
if Rails.env.production? && ENV['PROXY_URL'].present?
faraday.proxy = ENV['PROXY_URL']
end
faraday.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
faraday.options.timeout = 30
faraday.options.open_timeout = 10
faraday.request :retry, max: 3, interval: 2,
exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError]
faraday.response :raise_error
faraday.adapter :net_http
end
end
end
# Penggunaan dalam kontroler atau layanan:
# client = HttpClient.connection('https://api.example.com')
# response = client.get('/products', { category: 'electronics' })
Pola 2: Pengaturan melalui kredensial Rails. Untuk menyimpan data proxy, gunakan kredensial Rails yang terenkripsi:
# config/credentials.yml.enc (diedit melalui rails credentials:edit)
# proxy:
# host: proxy.example.com
# port: 8080
# username: your_user
# password: your_pass
# app/services/proxy_service.rb
class ProxyService
def self.faraday_proxy_config
creds = Rails.application.credentials.proxy
return nil unless creds
{
uri: "http://#{creds[:host]}:#{creds[:port]}",
user: creds[:username],
password: creds[:password]
}
end
def self.net_http_proxy
creds = Rails.application.credentials.proxy
return Net::HTTP::Proxy(nil, nil) unless creds
Net::HTTP::Proxy(
creds[:host],
creds[:port],
creds[:username],
creds[:password]
)
end
end
Pola 3: Tugas Latar Belakang dengan Sidekiq. Jika pemrosesan atau permintaan API dilakukan dalam pekerja latar belakang, pengaturan proxy tetap sama, tetapi penting untuk mempertimbangkan kompetisi:
# app/workers/price_parser_worker.rb
class PriceParserWorker
include Sidekiq::Worker
sidekiq_options retry: 3, queue: :parsers
def perform(product_url)
# Membuat koneksi baru untuk setiap pekerja
proxy = ProxyService.net_http_proxy
uri = URI(product_url)
proxy.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.read_timeout = 20
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = random_user_agent
response = http.request(request)
if response.code == '200'
parse_and_save(response.body, product_url)
else
Rails.logger.warn "Status tidak terduga #{response.code} untuk #{product_url}"
end
end
rescue Net::OpenTimeout, Net::ReadTimeout => e
Rails.logger.error "Timeout untuk #{product_url}: #{e.message}"
raise # Sidekiq akan mengulangi tugas
end
private
def random_user_agent
agents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
]
agents.sample
end
def parse_and_save(html, url)
# Logika pemrosesan...
end
end
Penanganan Kesalahan dan Timeout
Bekerja melalui proxy menambahkan lapisan tambahan yang dapat menghasilkan kesalahan spesifik. Penanganan pengecualian yang baik adalah perbedaan antara skrip yang akan gagal dalam 5 menit dan skrip yang berjalan selama berjam-jam tanpa intervensi.
Jenis kesalahan utama saat bekerja dengan proxy di Ruby:
| Pengecualian | Penyebab | Apa yang Harus Dilakukan |
|---|---|---|
Net::OpenTimeout |
Proxy tidak merespons | Ganti proxy, ulangi |
Net::ReadTimeout |
Proxy lambat atau situs tidak merespons | Tingkatkan timeout atau ganti proxy |
Errno::ECONNREFUSED |
Server proxy menolak koneksi | Periksa data proxy |
OpenSSL::SSL::SSLError |
Masalah dengan SSL melalui proxy | Periksa pengaturan SSL |
| HTTP 407 | Login/kata sandi proxy salah | Periksa kredensial |
| HTTP 403/429 | IP diblokir oleh situs | Ganti proxy, tambahkan jeda |
Penanganan kesalahan yang komprehensif dengan rotasi proxy otomatis:
require 'net/http'
require 'uri'
class RobustHttpClient
MAX_RETRIES = 3
RETRIABLE_ERRORS = [
Net::OpenTimeout,
Net::ReadTimeout,
Errno::ECONNREFUSED,
Errno::ECONNRESET,
OpenSSL::SSL::SSLError
].freeze
def initialize(proxies)
@proxies = proxies.dup
@failed_proxies = []
end
def get(url, retries: MAX_RETRIES)
uri = URI(url)
attempt = 0
begin
attempt += 1
proxy = current_proxy
proxy_class = Net::HTTP::Proxy(*proxy)
proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.open_timeout = 10
http.read_timeout = 20
request = Net::HTTP::Get.new(uri)
request['User-Agent'] = 'Mozilla/5.0 (compatible; RubyBot/1.0)'
response = http.request(request)
case response.code.to_i
when 200..299
response
when 407
raise "Autentikasi proxy gagal untuk #{proxy[0]}"
when 403, 429
rotate_proxy!
raise "IP diblokir (#{response.code}), rotasi proxy"
else
raise "Status HTTP yang tidak terduga: #{response.code}"
end
end
rescue *RETRIABLE_ERRORS => e
Rails.logger.warn "Kesalahan koneksi (upaya #{attempt}/#{retries}): #{e.message}"
rotate_proxy!
retry if attempt < retries
raise "Gagal setelah #{retries} upaya: #{e.message}"
rescue RuntimeError => e
Rails.logger.warn "Kesalahan HTTP (upaya #{attempt}/#{retries}): #{e.message}"
retry if attempt < retries
raise
end
end
private
def current_proxy
@proxies.first || raise("Tidak ada proxy yang tersedia!")
end
def rotate_proxy!
failed = @proxies.shift
@failed_proxies << failed
Rails.logger.info "Proxy diputar. Sisa: #{@proxies.length}"
end
end
Proxy SOCKS5 di Ruby: Pengaturan melalui socksify
Net::HTTP standar tidak mendukung SOCKS5 secara native — hanya proxy HTTP/HTTPS. Untuk bekerja dengan SOCKS5, diperlukan pustaka tambahan. Opsi yang paling populer adalah gem socksify.
Mengapa SOCKS5 bisa lebih disukai daripada proxy HTTP? Protokol SOCKS5 bekerja pada tingkat yang lebih rendah — ia memproksi semua lalu lintas TCP, bukan hanya HTTP. Selain itu, SOCKS5 mendukung autentikasi dan mengirimkan lebih sedikit metadata tentang permintaan, sehingga membuatnya kurang terlihat oleh sistem deteksi bot.
# Gemfile
# gem 'socksify'
require 'socksify'
require 'socksify/http'
require 'net/http'
require 'uri'
# Pengaturan global untuk proxy SOCKS5
TCPSocket::socks_server = 'proxy.example.com'
TCPSocket::socks_port = 1080
# Opsional: autentikasi (username/password SOCKS5)
# TCPSocket::socks_username = 'your_user'
# TCPSocket::socks_password = 'your_pass'
# Sekarang semua permintaan Net::HTTP berjalan melalui SOCKS5
uri = URI('https://httpbin.org/ip')
response = Net::HTTP.get_response(uri)
puts response.body
Perhatikan: saat menggunakan socksify, pengaturan diterapkan secara global ke semua koneksi TCP dalam proses. Jika Anda memerlukan pengaturan yang lebih fleksibel — gunakan Net::HTTP.SOCKSProxy dari gem yang sama:
require 'socksify/http'
# Membuat kelas proxy SOCKS5 (analog dengan Net::HTTP::Proxy untuk HTTP)
socks_proxy = Net::HTTP.SOCKSProxy('proxy.example.com', 1080)
uri = URI('https://httpbin.org/ip')
socks_proxy.start(uri.host, uri.port, use_ssl: true) do |http|
response = http.get(uri.path)
puts response.body
end
Untuk Faraday dengan SOCKS5, diperlukan adapter yang mendukung protokol ini. Opsi yang baik adalah faraday-net_http dalam kombinasi dengan socksify, atau menggunakan adapter berbasis curl faraday-typhoeus, yang secara native mendukung SOCKS5 melalui libcurl.
💡 Tips Memilih Protokol
Untuk sebagian besar tugas pemrosesan dan bekerja dengan API, cukup gunakan proxy HTTP/HTTPS — mereka lebih mudah diatur dan didukung secara native. SOCKS5 harus digunakan ketika Anda perlu memproksi tidak hanya lalu lintas HTTP, atau ketika proxy HTTP mudah terdeteksi oleh layanan tujuan. Proxy seluler dan residensial tersedia dalam kedua protokol.
Kesimpulan dan Rekomendasi
Mengatur proxy di Ruby tidak memerlukan pustaka yang rumit — Net::HTTP standar mendukung proxy HTTP "out of the box", dan Faraday membuat integrasi menjadi lebih nyaman berkat arsitektur middleware. Kesimpulan kunci dari panduan ini:
- Untuk Net::HTTP, gunakan
Net::HTTP::Proxy— ini adalah cara yang terintegrasi dan andal. - Untuk Faraday, parameter
faraday.proxymenerima string URI atau hash dengan kredensial. - Simpan data proxy di variabel lingkungan atau kredensial Rails — jangan hardcode dalam kode.
- Implementasikan rotasi proxy dan penanganan kesalahan untuk memastikan kerja yang andal di produksi.
- Tambahkan penundaan acak dan rotasi User-Agent untuk meniru perilaku manusia.
- Untuk SOCKS5, gunakan gem
socksify.
Pemilihan jenis proxy tergantung pada tugas. Jika Anda menulis parser untuk Wildberries atau Ozon — proxy residensial akan memberikan keseimbangan terbaik antara kecepatan dan menghindari perlindungan: IP nyata pengguna rumah sangat jarang masuk dalam daftar blokir. Untuk tugas yang sangat berat dengan volume permintaan besar ke sumber yang kurang dilindungi, proxy data center akan lebih cepat dan lebih murah per permintaan. Namun, jika skrip Ruby Anda bekerja dengan media sosial atau API iklan — perhatikan proxy seluler: alamat IP mereka memiliki tingkat kepercayaan tertinggi di sebagian besar platform.
```