A Ruby retry loop resends failed HTTP requests automatically, handling temporary errors like rate limits (429), server overload (500-504), and connection failures. This tutorial shows how to implement retry in Ruby using Net::HTTP with exponential backoff.
Create a Ruby Retry Loop
require "net/http"
require "uri"
MAX_ATTEMPTS = 5
RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504].freeze
def send_request(url)
uri = URI(url)
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"
Net::HTTP.start(
uri.hostname,
uri.port,
use_ssl: uri.scheme == "https",
open_timeout: 10,
read_timeout: 30
) do |http|
http.request(request)
end
end
parameters = URI.encode_www_form(
url: "https://www.scrapingbee.com"
)
request_url = "https://app.scrapingbee.com/api/v1/?#{parameters}"
1.upto(MAX_ATTEMPTS) do |attempt|
begin
response = send_request(request_url)
status_code = response.code.to_i
puts "Attempt #{attempt}: HTTP #{status_code}"
if status_code.between?(200, 299)
puts "Request successful."
puts response.body
break
end
unless RETRYABLE_STATUS_CODES.include?(status_code)
puts "The request failed with a non-retryable status code."
break
end
rescue StandardError => error
puts "Attempt #{attempt}: #{error.message}"
end
if attempt == MAX_ATTEMPTS
puts "Maximum retry limit reached."
break
end
delay = 2**(attempt - 1)
puts "Retrying in #{delay} seconds..."
sleep(delay)
end
How the Ruby Retry Logic Works
There is a maximum of five attempts in the script:
MAX_ATTEMPTS = 5
The script executes the retries for these temporary errors:
RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504].freeze
The delay increases after each failed attempt:
delay = 2**(attempt - 1)
Test the Failed Attempts
Change the request_url to a URL that returns a 503 error:
request_url = "https://httpbin.org/status/503"
The script will execute the retries across the 5 attempts, as shown below:

Go back to tutorials