From 2e69f7aca645059d70097c4beb5c088a022f50fc Mon Sep 17 00:00:00 2001 From: corbindavenport Date: Fri, 9 Oct 2026 16:06:46 -0400 Subject: [PATCH 1/2] Fix title formatting, update performance information --- README.md | 15 ++++----------- README.md.erb | 15 ++++----------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index b15ba15..3fe4a9d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Then install it with Bundler: bundle install ``` -## Quickstart +## Quick start [Create a SerpApi account](https://serpapi.com/users/sign_up?plan=free) to get your API key, then store it in an environment variable: @@ -116,7 +116,7 @@ results = client.search( Search-engine-specific parameters can also be supplied when creating the client or calling `search`. Parameters passed to `search` override client defaults. -### Search Asynchronous +### Asynchronous searches Search API features non-blocking search using the option: `async=true`. - Non-blocking - async=true - a single parent process can handle unlimited concurrent searches. @@ -210,7 +210,7 @@ pp results[:images_results] A [light variant](https://serpapi.com/google-images-light-api) engine called `google_images_light` is also available for faster, lower-cost image searches. -### Google Lens with File Upload +### Google Lens with file upload Upload an image with the Image API, then use its image ID in a Google Lens search. Uploaded image IDs expire after 10 minutes. @@ -358,16 +358,9 @@ Additional SDK resources: | **HTTP.rb Non-Persistent** | 270.62 req/s | 294.01 req/s | 319.81 req/s | **+8.6%** | **+8.8%** | | **HTTP.rb Persistent** | 347.04 req/s | 570.95 req/s | 456.93 req/s | **+64.5%** | **-20.0%** | -### Key Takeaways -1. **Upgrade to Ruby 3.4.4**: Clear performance benefits across all scenarios -2. **Use Persistent Connections**: 2x+ performance improvement in most cases -3. **HTTP.rb Performance**: Particularly benefits from Ruby 3.4.4 with persistent connections -4. **SerpApi Optimization**: Shows consistent ~2.2x improvement with persistent connections regardless of Ruby version -5. **Ruby 4.0.0 Performance**: Shows mixed results with some regressions compared to 3.4.4, particularly for HTTP.rb persistent connections. Ruby 4.0.0 was just released for Christmas 2025, and HTTP.rb has not been optimized for it yet. - The older library (google-search-results-ruby) was performing at 55 req/s on Ruby 2.7.8, which is 2x slower than the current version (serpapi-ruby) on Ruby 3.4.4 or 4.0.0. -**Context** This benchmark was performed on warmup search results using a MacBook Pro 2025 connected via Wi-Fi 6.0 home network on AT&T fiber from Austin, TX (no network optimization). +This benchmark was performed on warmup search results using a MacBook Pro 2025 connected via Wi-Fi 6.0 home network on AT&T fiber from Austin, TX (no network optimization). ## Contributing diff --git a/README.md.erb b/README.md.erb index b15ba15..3fe4a9d 100644 --- a/README.md.erb +++ b/README.md.erb @@ -26,7 +26,7 @@ Then install it with Bundler: bundle install ``` -## Quickstart +## Quick start [Create a SerpApi account](https://serpapi.com/users/sign_up?plan=free) to get your API key, then store it in an environment variable: @@ -116,7 +116,7 @@ results = client.search( Search-engine-specific parameters can also be supplied when creating the client or calling `search`. Parameters passed to `search` override client defaults. -### Search Asynchronous +### Asynchronous searches Search API features non-blocking search using the option: `async=true`. - Non-blocking - async=true - a single parent process can handle unlimited concurrent searches. @@ -210,7 +210,7 @@ pp results[:images_results] A [light variant](https://serpapi.com/google-images-light-api) engine called `google_images_light` is also available for faster, lower-cost image searches. -### Google Lens with File Upload +### Google Lens with file upload Upload an image with the Image API, then use its image ID in a Google Lens search. Uploaded image IDs expire after 10 minutes. @@ -358,16 +358,9 @@ Additional SDK resources: | **HTTP.rb Non-Persistent** | 270.62 req/s | 294.01 req/s | 319.81 req/s | **+8.6%** | **+8.8%** | | **HTTP.rb Persistent** | 347.04 req/s | 570.95 req/s | 456.93 req/s | **+64.5%** | **-20.0%** | -### Key Takeaways -1. **Upgrade to Ruby 3.4.4**: Clear performance benefits across all scenarios -2. **Use Persistent Connections**: 2x+ performance improvement in most cases -3. **HTTP.rb Performance**: Particularly benefits from Ruby 3.4.4 with persistent connections -4. **SerpApi Optimization**: Shows consistent ~2.2x improvement with persistent connections regardless of Ruby version -5. **Ruby 4.0.0 Performance**: Shows mixed results with some regressions compared to 3.4.4, particularly for HTTP.rb persistent connections. Ruby 4.0.0 was just released for Christmas 2025, and HTTP.rb has not been optimized for it yet. - The older library (google-search-results-ruby) was performing at 55 req/s on Ruby 2.7.8, which is 2x slower than the current version (serpapi-ruby) on Ruby 3.4.4 or 4.0.0. -**Context** This benchmark was performed on warmup search results using a MacBook Pro 2025 connected via Wi-Fi 6.0 home network on AT&T fiber from Austin, TX (no network optimization). +This benchmark was performed on warmup search results using a MacBook Pro 2025 connected via Wi-Fi 6.0 home network on AT&T fiber from Austin, TX (no network optimization). ## Contributing From 7731d05cf37fce288738106cfc3ad5ebcfebe519 Mon Sep 17 00:00:00 2001 From: corbindavenport Date: Fri, 9 Oct 2026 16:19:00 -0400 Subject: [PATCH 2/2] Delete erb template --- README.md.erb | 369 -------------------------------------------------- 1 file changed, 369 deletions(-) delete mode 100644 README.md.erb diff --git a/README.md.erb b/README.md.erb deleted file mode 100644 index 3fe4a9d..0000000 --- a/README.md.erb +++ /dev/null @@ -1,369 +0,0 @@ -# SerpApi Ruby Library - -[![serpapi-ruby](https://github.com/serpapi/serpapi-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/serpapi/serpapi-ruby/actions/workflows/ci.yml) [![Gem Version](https://badge.fury.io/rb/serpapi.svg)](https://badge.fury.io/rb/serpapi) - -Integrate search data into your AI workflow, RAG, fine-tuning, or Ruby application using this official [SerpApi Ruby SDK](https://serpapi.com/integrations/ruby). [SerpApi](https://serpapi.com) supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and many more. - -## Installation - -Ruby 2.7 or later is required. - -Install the SDK directly with RubyGems: - -```bash -gem install serpapi -``` - -Or add it to your application's `Gemfile`: - -```ruby -gem "serpapi" -``` - -Then install it with Bundler: - -```bash -bundle install -``` - -## Quick start - -[Create a SerpApi account](https://serpapi.com/users/sign_up?plan=free) to get your API key, then store it in an environment variable: - -```bash -export SERPAPI_KEY="your_api_key" -``` - -Run a Google search and access the results as a Ruby `Hash`: - -```ruby -require "serpapi" -require "pp" - -client = SerpApi::Client.new( - engine: "google", - api_key: ENV.fetch("SERPAPI_KEY") -) - -results = client.search(q: "coffee") -pp results[:organic_results] - -client.close -``` - -## Features - -- [Asynchronous searches](./demo/demo_async.rb) for submitting non-blocking jobs and retrieving completed results from the Search Archive API. -- [Persistent connections and connection pooling](./demo/demo_thread_pool.rb) for reusing HTTP connections across searches. -- Search results as Ruby hashes with `search`, token-efficient Markdown with `md`, or raw search-engine HTML with `html`. -- SDK methods for the [Image API](https://serpapi.com/image-api), [Location API](https://serpapi.com/locations-api), [Search Archive API](https://serpapi.com/search-archive-api), and [Account API](https://serpapi.com/account-api). -- Configurable HTTP timeouts and symbolized or string JSON keys. - -## Response formats - -Use `search` for structured results decoded into a Ruby `Hash`: - -```ruby -results = client.search(q: "coffee") -``` - -Use `md` for a token-efficient Markdown `String` optimized for LLMs and AI agents: - -```ruby -markdown = client.md(q: "coffee") -``` - -Use `html` when you need the raw search-engine response: - -```ruby -raw_html = client.html(q: "coffee") -``` - -Archived results are also available as Markdown with `client.search_archive(search_id, :md)`. - -Learn more about [SerpApi Markdown output](https://serpapi.com/markdown-output). - -## Configuration - -Set defaults when creating a client, then override search parameters in individual calls: - -```ruby -client = SerpApi::Client.new( - api_key: ENV.fetch("SERPAPI_KEY"), - engine: "google", - hl: "en", - gl: "us", - persistent: true, - timeout: 120 -) - -results = client.search( - q: "coffee", - gl: "gb", - async: false, - symbolize_names: true -) -``` - -| Option | Default | Description | -| --- | --- | --- | -| `api_key` | None | Your SerpApi API key. Use an environment variable rather than committing it to source control. | -| `engine` | None | The search engine used by default, such as `google` or `google_maps`. | -| `persistent` | `true` | Reuses the HTTP connection between requests. Call `client.close` when finished. | -| `timeout` | `120` | Timeout in seconds for non-persistent HTTP requests. | -| `async` | `false` | Submits searches without waiting for them to complete. It can be set on the client or per search. | -| `symbolize_names` | `true` | Returns JSON object keys as symbols. Pass `false` to a search to receive string keys. | - -Search-engine-specific parameters can also be supplied when creating the client or calling `search`. Parameters passed to `search` override client defaults. - -### Asynchronous searches - -Search API features non-blocking search using the option: `async=true`. - - Non-blocking - async=true - a single parent process can handle unlimited concurrent searches. - - Blocking - async=false - many processes must be forked and synchronized to handle concurrent searches. This strategy is I/O usage because each client would hold a network connection. - -Search API enables `async` search. - - Non-blocking (`async=true`) : the development is more complex, but this allows handling many simultaneous connections. - - Blocking (`async=false`) : it is easy to write the code but more compute-intensive when the parent process needs to hold many connections. - -Here is an example of asynchronous searches using Ruby -```ruby -require 'serpapi' - -company_list = %w[meta amazon apple netflix google] -client = SerpApi::Client.new(engine: 'google', async: true, persistent: true, api_key: ENV['SERPAPI_KEY']) -schedule_search = Queue.new -result = nil -company_list.each do |company| - result = client.search(q: company) - puts "#{company}: search results found in cache for: #{company}" if result[:search_metadata][:status] =~ /Cached/ - - schedule_search.push(result[:search_metadata][:id]) -end - -puts "Last search submited at: #{result[:search_metadata][:created_at]}" - -puts 'wait 10s for all requests to be completed ' -sleep(10) - -puts 'wait until all searches are cached or success' -until schedule_search.empty? - search_id = schedule_search.pop - - search_archived = client.search_archive(search_id) - - company = search_archived[:search_parameters][:q] - - if search_archived[:search_metadata][:status] =~ /Cached|Success/ - puts "#{search_archived[:search_parameters][:q]}: search results found in archive for: #{company}" - next - end - - schedule_search.push(search_id) -end - -schedule_search.close -puts 'done' -``` - - * source code: [demo/demo_async.rb](https://github.com/serpapi/serpapi-ruby/blob/master/demo/demo_async.rb) - -This code shows a simple solution to batch searches asynchronously into a [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)). Each search may take up to few seconds to complete. By the time the first element pops out of the queue, the search results might already be available in the archive. If not, the `search_archive` method blocks until the search results are available. - -## Examples - -Here are some examples for some of our most popular APIs. You can find the full list of supported engines and parameters in our [documentation](https://serpapi.com/search-engine-apis). - -### Google Shopping - -Scrape Google Shopping results with product names, prices, ratings, and merchant information. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'google_shopping', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'Macbook M4') -pp results[:shopping_results] -``` - -[See documentation](https://serpapi.com/google-shopping-api) - -**Google Shopping Light** - -A [light variant](https://serpapi.com/google-shopping-light-api) engine called `google_shopping_light` is also available for faster, lower-cost shopping searches. - -### Google Images - -Scrape Google Images search results, including image URLs, thumbnails, titles, and source pages. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'google_images', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'coffee') -pp results[:images_results] -``` - -[See documentation](https://serpapi.com/images-results) - -**Google Images Light** - -A [light variant](https://serpapi.com/google-images-light-api) engine called `google_images_light` is also available for faster, lower-cost image searches. - -### Google Lens with file upload - -Upload an image with the Image API, then use its image ID in a Google Lens search. Uploaded image IDs expire after 10 minutes. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(api_key: ENV['SERPAPI_KEY']) -upload = client.upload_image('./image.jpg') -results = client.search(engine: 'google_lens', image_id: upload[:image_id]) -pp results[:visual_matches] -``` - -[See Image API documentation](https://serpapi.com/image-api) · [See Google Lens image upload documentation](https://serpapi.com/google-lens-upload-an-image) - -### Google Trends - -Track search interest over time and compare the popularity of search terms. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'google_trends', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'coffee', data_type: 'TIMESERIES') -pp results[:interest_over_time] -``` - -[See documentation](https://serpapi.com/google-trends-api) - -### Google Flights - -Search flight routes, schedules, prices, and booking options. - -> **Note:** The `google_flights` engine does not use `q`. Specify route and date parameters such as `departure_id`, `arrival_id`, `outbound_date`, and `return_date`. - -```ruby -require 'date' -require 'serpapi' - -outbound_date = (Date.today + 30).iso8601 -return_date = (Date.today + 37).iso8601 -client = SerpApi::Client.new(engine: 'google_flights', api_key: ENV['SERPAPI_KEY']) -results = client.search( - departure_id: 'LAX', - arrival_id: 'AUS', - outbound_date: outbound_date, - return_date: return_date -) -flights = results[:best_flights] || results[:other_flights] -pp flights -``` - -[See documentation](https://serpapi.com/google-flights-api) - -### Google AI Mode API - -The Google AI Mode API returns AI-generated answers with structured text blocks, references, images, products, and more. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'google_ai_mode', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'best coffee maker') -pp results[:reconstructed_markdown] -``` - -[See documentation](https://serpapi.com/google-ai-mode-api) - -### Bing Search - -Scrape Bing web search results, including organic results, ads, related searches, and more. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'bing', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'coffee') -pp results[:organic_results] -``` - -[See documentation](https://serpapi.com/bing-search-api) - -### DuckDuckGo Search - -Scrape DuckDuckGo search results, including organic results, ads, knowledge graphs, and related searches. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'duckduckgo', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'coffee') -pp results[:organic_results] -``` - -[See documentation](https://serpapi.com/duckduckgo-search-api) - -### Baidu Search - -Scrape Baidu search results, including organic results, answer boxes, and related searches. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'baidu', api_key: ENV['SERPAPI_KEY']) -results = client.search(q: 'coffee') -pp results[:organic_results] -``` - -[See documentation](https://serpapi.com/baidu-search-api) - -### Amazon Search - -Scrape Amazon product search results, including product names, prices, ratings, reviews, and availability. - -> **Note:** The `amazon` engine uses the `k` parameter for a keyword search, not `q`. - -```ruby -require 'serpapi' - -client = SerpApi::Client.new(engine: 'amazon', api_key: ENV['SERPAPI_KEY']) -results = client.search(k: 'coffee') -pp results[:organic_results] -``` - -[See documentation](https://serpapi.com/amazon-search-api) - -## Documentation - -SerpApi supports Google Search, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, Apple App Store, and many other APIs. Browse the [SerpApi documentation](https://serpapi.com/search-api) to find supported APIs and parameters, or use the [Playground](https://serpapi.com/playground) to build a request and generate Ruby code. - -Additional SDK resources: - -- [Ruby SDK integration page](https://serpapi.com/integrations/ruby) -- [Ruby SDK API reference](https://rubydoc.info/github/serpapi/serpapi-ruby/master) -- [RubyGems package](https://rubygems.org/gems/serpapi) -- [SerpApi status](https://serpapi.com/status) - -## Performance - -### Ruby 4.0.0 vs 3.4.4 vs Ruby 2.7.8 Performance - -| Metric | Ruby 2.7.8 | Ruby 3.4.4 | Ruby 4.0.0 | Improvement (3.4.4 vs 2.7.8) | Improvement (4.0.0 vs 3.4.4) | -|--------|------------|------------|------------|------------------------------|------------------------------| -| **SerpApi Non-Persistent** | 100.93 req/s | 114.97 req/s | 120.09 req/s | **+13.9%** | **+4.5%** | -| **SerpApi Persistent** | 226.82 req/s | 255.07 req/s | 296.05 req/s | **+12.4%** | **+16.1%** | -| **HTTP.rb Non-Persistent** | 270.62 req/s | 294.01 req/s | 319.81 req/s | **+8.6%** | **+8.8%** | -| **HTTP.rb Persistent** | 347.04 req/s | 570.95 req/s | 456.93 req/s | **+64.5%** | **-20.0%** | - -The older library (google-search-results-ruby) was performing at 55 req/s on Ruby 2.7.8, which is 2x slower than the current version (serpapi-ruby) on Ruby 3.4.4 or 4.0.0. - -This benchmark was performed on warmup search results using a MacBook Pro 2025 connected via Wi-Fi 6.0 home network on AT&T fiber from Austin, TX (no network optimization). - -## Contributing - -Contributions are welcome. Make sure to read our [contributing guide](https://github.com/serpapi/serpapi-ruby/blob/master/CONTRIBUTING.md). - -© 2026 [SerpApi](https://serpapi.com)