diff --git a/.gitignore b/.gitignore index eb29f61..974c7b2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ derive.rb gradlew.bat switch_java.sh .DS_Store +.vscode/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..07eccae --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +## Changelog +**1.2.0** (latest) — Add markdown support, improve error handling if corrupt data received + +**1.1.0** — Java 21, Gradle 8.x; ongoing API and example updates + +**1.0.0** — Revisit API naming and align the client with serpapi.com \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8eae938 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contributing + +## Key Goals + +- Brand centric instead of search engine based + - No hard-coded logic per search engine +- Simple HTTP client (lightweight, reduced dependency) + - No magic default values + - Thread safe +- Easy extension +- Defensive code style (raise a custom exception) +- TDD - Test driven development +- Best API coding practice per platform +- KISS principles + +## Code Quality Expectations + + +We use JUnit, GitHub Actions (see workflow), and Gradle. + +Run the full test suite locally (integration tests call the live API when a key is present): + +```bash +export SERPAPI_KEY='your_key' # optional: without it, many tests skip; some tests require the key and will fail if unset +./gradlew test +``` + +Regenerate README.md from the template after editing examples: + +```bash +make readme # requires Ruby `erb` +``` + +How to build from source +Clone the repository: + +```bash +git clone https://github.com/serpapi/serpapi-java.git +cd serpapi-java +``` + +Build (use the wrapper): + +```bash +./gradlew build +``` + +The main library JAR is under build/libs/ (for example serpapi-1.1.0.jar, name follows version in build.gradle). Copy it into your project’s lib/ directory if you are not using Maven/Gradle dependency resolution. \ No newline at end of file diff --git a/README.md b/README.md index 42906a6..3b1019d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ - # SerpApi Java Library [![serpapi-java](https://github.com/serpapi/serpapi-java/actions/workflows/gradle.yml/badge.svg)](https://github.com/serpapi/serpapi-java/actions/workflows/gradle.yml) [![JitPack](https://jitpack.io/v/serpapi/serpapi-java.svg)](https://jitpack.io/#serpapi/serpapi-java) -Integrate search data into your Java application. This library is the official wrapper for [SerpApi](https://serpapi.com). - -SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and more. +Integrate search data into your AI workflow, RAG, fine-tuning, or Java application using this official [SerpApi Java SDK](https://serpapi.com/integrations/java). -[The full documentation is available here.](https://serpapi.com/search-api) +[SerpApi](https://serpapi.com/) supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and many more. ## Installation -Using Maven / Gradle. +Installation of the serpapi-java package is done using Maven / Gradle. + +Any new project should include these lines in a `build.gradle` file. -Edit your `build.gradle` file: ```gradle repositories { maven { url "https://jitpack.io" } @@ -25,14 +23,18 @@ dependencies { } ``` -To list all available versions: +To list all available versions see: https://jitpack.io/api/builds/com.github.serpapi/serpapi-java -or you can download the jar file from https://github.com/serpapi/serpapi-java/releases +or you can download the jar file from https://github.com/serpapi/serpapi-java/releases. + +_Note: JitPack builds Maven artifacts from GitHub releases and tags._ -Note: JitPack builds Maven artifacts from GitHub releases and tags. +## Quickstart Tutorial -## Usage +[Create a SerpApi account](https://serpapi.com/dashboard) to get your API key, then store it in an environment variable: + +```export SERPAPI_KEY="your_api_key"``` To try the library quickly, use the demo project: ```bash @@ -40,15 +42,18 @@ git clone https://github.com/serpapi/serpapi-java.git cd serpapi-java/demo make all SERPAPI_KEY='' ``` -Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard +Use quotes if your key contains shell-special characters. + +The `serpapi-java` package is already installed inside the `build.gradle` file of this cloned `serpapi-java` repository. + +So, in this tutorial, no extra setup is needed. +For future projects please refer to the above provided 'Installation' section. `demo/src/main/java/demo/App.java`: ```java class App { public static void main(String[] args) { String apiKey = System.getenv("SERPAPI_KEY"); - - // set search location String location = "Austin,Texas"; String engine = "google"; System.out.println("find the first coffee shop in " + location + " using " + engine); @@ -56,18 +61,13 @@ class App { Map auth = new HashMap<>(); auth.put("engine", engine); auth.put("api_key", apiKey); + SerpApi serpapi = new SerpApi(auth); - // create client - SerpApi serpapi= new SerpApi(auth); - - // create search parameters Map parameter = new HashMap<>(); parameter.put("q", "Coffee"); parameter.put("location", location); - // perform search try { - // get search results JsonObject data = serpapi.search(parameter); JsonArray organic = data.getAsJsonArray("organic_results"); JsonObject first = organic.get(0).getAsJsonObject(); @@ -81,13 +81,32 @@ class App { } ``` -The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a list of all the possible parameters that can be passed to the API. +## Features +- Asynchronous searches for submitting non-blocking jobs and retrieving completed results from the Search Archive API +- Search results stored as a [Gson](https://github.com/google/gson) for JSON and returns responses as Gson `JsonObject` / `JsonArray` 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) -## Documentation +## Response Formats + +Use `search` for structured results decoded into a `Gson JsonObject / JsonArray`: + +```results = client.search(parameter);``` + +Use `md` for a token-efficient Markdown String optimized for LLMs and AI agents: -- [SerpApi Search API](https://serpapi.com/search-api) — parameters, engines, and response formats -- After cloning, run `./gradlew javadoc` and open `build/docs/javadoc/index.html` for this library’s Javadoc. +```markdown = client.markdown(parameter);``` + +Use `html` when you need the raw search-engine response: + +```rawHtml = client.html(parameter);``` + +Learn more about [SerpApi Markdown output](https://serpapi.com/markdown-output). + +> A couple of notes: +> - `client` is a `SerpApi` instance you create with your API key, e.g. `SerpApi client = new SerpApi(auth);` where `auth` is a `Map` containing `"api_key"` (and typically `"engine"`). +> - `parameter` is a `Map` with your search parameters (`q`, `location`, etc.). +> - `client.markdown(parameter)` is new as of `serpapi-java` **1.2.0** - make sure your `build.gradle` dependency is at least that version ## Requirements @@ -97,462 +116,416 @@ This library uses [Gson](https://github.com/google/gson) for JSON and returns re **Consumers** of the JitPack artifact should run a JVM whose version is at least the **bytecode level** of the release you depend on (releases from this branch target **Java 21**). +## Configuration -### Location API -```java -SerpApi serpapi = new SerpApi(); - -Map parameter = new HashMap(); -parameter.put("q", "Austin"); -parameter.put("limit", "3"); -JsonArray location = serpapi.location(parameter); -System.out.println(location.get(0).getAsJsonObject().get("name").getAsString()); -// Prints the first matching name among up to 3 results (see LocationApiTest for a JUnit example). -``` - -[LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) - -### Search Archive API - -Run a search to obtain a `search_id`. +Set defaults when creating a client, then override search parameters in individual calls: ```java Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi serpapi = new SerpApi(auth); +auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("engine", "google"); +auth.put("hl", "en"); +auth.put("gl", "us"); +SerpApi client = new SerpApi(auth); Map parameter = new HashMap<>(); -parameter.put("q", "Coffee"); -parameter.put("location", "Austin, Texas, United States"); -parameter.put("hl", "en"); -parameter.put("gl", "us"); -parameter.put("google_domain", "google.com"); -parameter.put("safe", "active"); -parameter.put("start", "10"); -parameter.put("device", "desktop"); -JsonObject results = serpapi.search(parameter); -``` - -Retrieve the same search from the archive: -```java -// now search in the archive -String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id").getAsString(); +parameter.put("q", "coffee"); +parameter.put("gl", "gb"); +parameter.put("async", "false"); -// retrieve search from the archive with speed for free -JsonObject archive = serpapi.searchArchive(id); -System.out.println(archive.toString()); +try { + JsonObject results = client.search(parameter); +} catch (SerpApiException e) { + e.printStackTrace(); +} ``` -The archived JSON matches the original search result. In tests, the key is supplied via `System.getenv("SERPAPI_KEY")`; see `SerpApiTest.java`. -[SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) +| Field | 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. | +| `async` | false | Submits searches without waiting for them to complete. It can be set on the client or per search. | -### Account API +Search-engine-specific parameters can also be supplied when creating the client or calling `search`. Parameters passed to search override client defaults. -```java -Map parameter = new HashMap<>(); -parameter.put("api_key", "your_api_key"); - -SerpApi serpapi = new SerpApi(parameter); -JsonObject account = serpapi.account(); -System.out.println(account.toString()); -``` -it prints your account information. +### Search Asynchronous +Search API features non-blocking search using the option: `async=true`. -[AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) +- Non-blocking - `async=true` - a single thread can submit many searches without waiting for each one to complete, then collects results later from the Search Archive API. +- Blocking - `async=false` - each search call blocks the calling thread until results are ready. To run searches concurrently, you'd need multiple threads (i.e. through an `ExecutorService`), each holding its own connection open for the duration of its search. This is more I/O-intensive, since concurrency requires as many held-open connections as concurrent searches. -### Markdown output +Here is an example simulation of asynchronous searches using Java: + + ```java +String apiKey = System.getenv("SERPAPI_KEY"); -```java Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); auth.put("engine", "google"); -SerpApi serpapi = new SerpApi(auth); +auth.put("api_key", apiKey); +auth.put("async", "true"); +SerpApi client = new SerpApi(auth); -Map parameter = new HashMap<>(); -parameter.put("q", "coffee"); -System.out.println(serpapi.markdown(parameter)); -``` -it prints the results as raw markdown, intended for LLM and agent consumption. +Queue ids = new LinkedList<>(); -[MarkdownApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/MarkdownApiTest.java) +for (String company : new String[]{"meta", "amazon", "apple", "netflix", "google"}) { + Map parameter = new HashMap<>(); + parameter.put("q", company); -## Examples in Java + JsonObject result = client.search(parameter); + ids.add(result.getAsJsonObject("search_metadata").get("id").getAsString()); +} -### Search bing -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +System.out.println("waiting 10s for searches to complete..."); +// for production use cases, continuous polling instead of waiting is necessary +Thread.sleep(10000); -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "bing"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +while (!ids.isEmpty()) { + JsonObject archived = client.searchArchive(ids.poll()); + String status = archived.getAsJsonObject("search_metadata").get("status").getAsString(); + String company = archived.getAsJsonObject("search_parameters").get("q").getAsString(); + System.out.println(company + ": " + status); +} ``` - * source code: [src/test/java/serpapi/example/BingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BingTest.java) -see: [https://serpapi.com/bing-search-api](https://serpapi.com/bing-search-api) +This code shows a simple solution to batch searches asynchronously into a [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)). -### Search baidu -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +Each search may take a 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. -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "baidu"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +If not, the `searchArchive` method blocks until the search results are available. - * source code: [src/test/java/serpapi/example/BaiduTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BaiduTest.java) -see: [https://serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api) +## Examples -### Search yahoo -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +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). -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "yahoo"); -parameter.put("p", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +### Google Shopping - * source code: [src/test/java/serpapi/example/YahooTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/YahooTest.java) -see: [https://serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api) +Scrape Google Shopping results with product names, prices, ratings, and merchant information. -### Search youtube ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_shopping"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "youtube"); -parameter.put("search_query", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("q", "Macbook M4"); + +try { + JsonObject data = client.search(parameter); + JsonArray results = data.getAsJsonArray("shopping_results"); + if (results != null && results.size() > 0) { + JsonObject first = results.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/YoutubeTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/YoutubeTest.java) -see: [https://serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api) - -### Search walmart -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +Source code: [src/test/java/serpapi/example/GoogleShoppingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleShoppingTest.java) -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "walmart"); -parameter.put("query", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +[See documentation](https://serpapi.com/google-shopping-api) - * source code: [src/test/java/serpapi/example/WalmartTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/WalmartTest.java) -see: [https://serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api) +#### Google Shopping Light -### Search ebay -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +A [light variant](https://serpapi.com/google-shopping-light-api) engine called `google_shopping_light` is also available for faster, lower-cost shopping searches. -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "ebay"); -parameter.put("_nkw", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +### Google Images - * source code: [src/test/java/serpapi/example/EbayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/EbayTest.java) -see: [https://serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api) +Scrape Google Images search results, including image URLs, thumbnails, titles, and source pages. -### Search naver ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_images"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "naver"); -parameter.put("query", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("q", "coffee"); + +try { + JsonObject data = client.search(parameter); + JsonArray results = data.getAsJsonArray("images_results"); + if (results != null && results.size() > 0) { + JsonObject first = results.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/NaverTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/NaverTest.java) -see: [https://serpapi.com/naver-search-api](https://serpapi.com/naver-search-api) +Source code: [src/test/java/serpapi/example/GoogleImagesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleImagesTest.java) -### Search home depot -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +[See documentation](https://serpapi.com/images-results) -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "home_depot"); -parameter.put("q", "table"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +#### 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. - * source code: [src/test/java/serpapi/example/HomeDepotTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/HomeDepotTest.java) -see: [https://serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api) +### Google Lens + +Scrape results from the Google Lens page when performing an image search. The results related to the image could contain visual matches and other data. -### Search apple app store ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_lens"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "apple_app_store"); -parameter.put("term", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("url", "https://i.imgur.com/your_image.png"); + +try { + JsonObject data = client.search(parameter); + JsonArray visualMatches = data.getAsJsonArray("visual_matches"); + System.out.println(visualMatches); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/AppleAppStoreTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/AppleAppStoreTest.java) -see: [https://serpapi.com/apple-app-store](https://serpapi.com/apple-app-store) +Source code: [src/test/java/serpapi/example/GoogleLensTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleLensTest.java) -### Search duckduckgo -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +[See Image API documentation](https://serpapi.com/image-api) · [See Google Lens image upload documentation](https://serpapi.com/google-lens-upload-an-image) -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "duckduckgo"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +### Google Trends - * source code: [src/test/java/serpapi/example/DuckduckgoTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/DuckduckgoTest.java) -see: [https://serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api) +Track search interest over time and compare the popularity of search terms. -### Search google ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_trends"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google"); parameter.put("q", "coffee"); -parameter.put("engine", "google"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +parameter.put("data_type", "TIMESERIES"); - * source code: [src/test/java/serpapi/example/GoogleTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleTest.java) -see: [https://serpapi.com/search-api](https://serpapi.com/search-api) +try { + JsonObject data = client.search(parameter); + JsonObject interestOverTime = data.getAsJsonObject("interest_over_time"); -### Search google scholar -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); + if (interestOverTime != null) { + JsonArray timelineData = interestOverTime.getAsJsonArray("timeline_data"); -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "google_scholar"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); + if (timelineData != null && timelineData.size() > 0) { + JsonObject first = timelineData.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/GoogleScholarTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleScholarTest.java) -see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api) +Source code: [src/test/java/serpapi/example/GoogleTrendsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleTrendsTest.java) -### Search google autocomplete -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +[See documentation](https://serpapi.com/google-trends-api) -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "google_autocomplete"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); -``` +### Google Flights +Search flight routes, schedules, prices, and booking options. - * source code: [src/test/java/serpapi/example/GoogleAutocompleteTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleAutocompleteTest.java) -see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api) +_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`._ -### Search google product ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_flights"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search +String outboundDate = LocalDate.now().plusDays(7).toString(); +String returnDate = LocalDate.now().plusDays(14).toString(); + Map parameter = new HashMap<>(); -parameter.put("engine", "google_product"); -parameter.put("q", "coffee"); -parameter.put("product_id", "4887235756540435899"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("departure_id", "LAX"); +parameter.put("arrival_id", "AUS"); +parameter.put("outbound_date", outboundDate); +parameter.put("return_date", returnDate); + +try { + JsonObject data = client.search(parameter); + JsonArray bestFlights = data.getAsJsonArray("best_flights"); + //JsonArray otherFlights = data.getAsJsonArray("other_flights"); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(bestFlights)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` +Source code: [src/test/java/serpapi/example/GoogleFlightsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleFlightsTest.java) - * source code: [src/test/java/serpapi/example/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleProductTest.java) +[See documentation](https://serpapi.com/google-flights-api) -see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) +### Google AI Mode API +The Google AI Mode API returns AI-generated answers with structured text blocks, references, images, products, and more. -### Search google reverse image ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_ai_mode"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("engine", engine); +auth.put("api_key", apiKey); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_reverse_image"); -parameter.put("image_url", "https://i.imgur.com/5bGzZi7.jpg"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("q", "best coffee maker"); + +try { + String markdownData = client.markdown(parameter); + System.out.println(markdownData); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/GoogleReverseImageTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleReverseImageTest.java) -see: [https://serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image) +Source code: [src/test/java/serpapi/example/GoogleAIModeTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleAIModeTest.java) -### Search google events -```java -// setup serpapi client -Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi client = new SerpApi(auth); +[See documentation](https://serpapi.com/google-ai-mode-api) -// run search -Map parameter = new HashMap<>(); -parameter.put("engine", "google_events"); -parameter.put("q", "Events in Austin, TX"); -JsonObject results = client.search(parameter); -JsonArray events = results.getAsJsonArray("events_results"); -System.out.println(results.toString()); -``` +### Bing Search - * source code: [src/test/java/serpapi/example/GoogleEventsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleEventsTest.java) -see: [https://serpapi.com/google-events-api](https://serpapi.com/google-events-api) +Scrape Bing web search results, including organic results, ads, related searches, and more. -### Search google maps ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "bing"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", apiKey); +auth.put("engine", engine); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_maps"); -parameter.put("q", "pizza"); -parameter.put("ll", "@40.7455096,-74.0083012,15.1z"); -parameter.put("type", "search"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("q", "coffee"); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/GoogleMapsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleMapsTest.java) -see: [https://serpapi.com/google-maps-api](https://serpapi.com/google-maps-api) +Source code: [src/test/java/serpapi/example/BingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BingTest.java) + +[See documentation](https://serpapi.com/bing-search-api) + +### DuckDuckGo Search + +Scrape DuckDuckGo search results, including organic results, ads, knowledge graphs, and related searches. -### Search google jobs ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "duckduckgo"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", apiKey); +auth.put("engine", engine); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_jobs"); parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/GoogleJobsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleJobsTest.java) -see: [https://serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api) +Source code: [src/test/java/serpapi/example/DuckduckgoTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/DuckduckgoTest.java) + +[See documentation](https://serpapi.com/duckduckgo-search-api) + +### Baidu Search + +Scrape Baidu search results, including organic results, answer boxes, and related searches. -### Search google play ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "baidu"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", apiKey); +auth.put("engine", engine); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_play"); -parameter.put("q", "kite"); -parameter.put("store", "apps"); -JsonObject results = client.search(parameter); -JsonArray sections = results.getAsJsonArray("organic_results"); -int appCount = 0; -for (JsonElement section : sections) { - JsonObject sectionObj = section.getAsJsonObject(); - if (sectionObj.has("items") && sectionObj.get("items").isJsonArray()) { - appCount += sectionObj.getAsJsonArray("items").size(); - } +parameter.put("q", "coffee"); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); } -System.out.println(results.toString()); ``` - * source code: [src/test/java/serpapi/example/GooglePlayTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GooglePlayTest.java) -see: [https://serpapi.com/google-play-api](https://serpapi.com/google-play-api) +Source code: [src/test/java/serpapi/example/BaiduTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BaiduTest.java) + +[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`._ -### Search google images ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "amazon"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", apiKey); +auth.put("engine", engine); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_images"); -parameter.put("engine", "google_images"); -parameter.put("tbm", "isch"); -parameter.put("q", "coffee"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +parameter.put("k", "coffee"); +parameter.put("amazon_domain", "amazon.com"); + +try { + JsonObject data = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(data)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` +Source code: [src/test/java/serpapi/example/AmazonSearchTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/AmazonSearchTest.java) - * source code: [src/test/java/serpapi/example/GoogleImagesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleImagesTest.java) -see: [https://serpapi.com/images-results](https://serpapi.com/images-results) +[See documentation](https://serpapi.com/amazon-search-api) ## Migration from google-search-results-java @@ -571,17 +544,17 @@ implementation 'com.github.serpapi:serpapi-java:1.2.0' ### Class and method renames -| Old (`google-search-results-java`) | New (`serpapi-java`) | -|------------------------------------|----------------------| -| `GoogleSearch` | `SerpApi` | -| `SerpApiSearch` | `SerpApi` | -| `client.getJson()` | `client.search(parameter)` | -| `client.getHtml()` | `client.html(parameter)` | -| — | `client.markdown(parameter)` — new in 1.2.0, see [Markdown output](#markdown-output) | -| `client.getSearchArchive(id)` | `client.searchArchive(id)` | -| `client.getAccount()` | `client.account()` | -| `client.getLocation(parameter)` | `client.location(parameter)` | -| `SerpApiSearchException` | `SerpApiException` | +| Old (`google-search-results-java`) | New (`serpapi-java`) | +| ---------------------------------- | ------------------------------------------------------------------------------------ | +| `GoogleSearch` | `SerpApi` | +| `SerpApiSearch` | `SerpApi` | +| `client.getJson()` | `client.search(parameter)` | +| `client.getHtml()` | `client.html(parameter)` | +| — | `client.markdown(parameter)` — new in 1.2.0 | +| `client.getSearchArchive(id)` | `client.searchArchive(id)` | +| `client.getAccount()` | `client.account()` | +| `client.getLocation(parameter)` | `client.location(parameter)` | +| `SerpApiSearchException` | `SerpApiException` | ### Example @@ -604,37 +577,15 @@ parameter.put("engine", "google"); JsonObject results = client.search(parameter); ``` -### Contributing - -We use JUnit, **GitHub Actions** (see [workflow](https://github.com/serpapi/serpapi-java/blob/master/.github/workflows/gradle.yml)), and Gradle. - -Run the full test suite locally (integration tests call the live API when a key is present): - -```bash -export SERPAPI_KEY='your_key' # optional: without it, many tests skip; some tests require the key and will fail if unset -./gradlew test -``` - -Regenerate `README.md` from the template after editing examples: - -```bash -make readme # requires Ruby `erb` -``` - -#### How to build from source +## Documentation -Clone the repository: -```bash -git clone https://github.com/serpapi/serpapi-java.git -cd serpapi-java -``` +SerpApi supports Google Search, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, Apple App Store, and many other APIs. Browse the [SerpApi](https://serpapi.com/search-api) documentation to find supported APIs and parameters, or use the [Playground](https://serpapi.com/playground) to build a request and generate code. -Build (use the wrapper): -```bash -./gradlew build -``` +Additional SDK resources: -The main library JAR is under `build/libs/` (for example `serpapi-1.1.0.jar`, name follows `version` in `build.gradle`). Copy it into your project’s `lib/` directory if you are not using Maven/Gradle dependency resolution. +- [Java SDK integration page](https://serpapi.com/integrations/java) +- [Java package](https://github.com/serpapi/serpapi-java) +- [SerpApi status](https://serpapi.com/status) ## TLS / HTTPS and older JVMs ### Symptom @@ -657,15 +608,12 @@ java -version On Windows, install a current JDK from your vendor and point `JAVA_HOME` at it. -### Inspiration +## Inspiration * https://www.baeldung.com/java-http-request * https://github.com/google/gson - -## License -MIT license -## Changelog -- 1.2.0 — Add markdown support, improve error handling if corrupt data received -- 1.1.0 — Java 21, Gradle 8.x; ongoing API and example updates -- 1.0.0 — Revisit API naming and align the client with serpapi.com +## Contributing + +Contributions are welcome. Make sure to read our [contributing guide](https://github.com/serpapi/serpapi-java/blob/master/CONTRIBUTING.md) +© 2026 [SerpApi](https://serpapi.com/) \ No newline at end of file diff --git a/README.md.erb b/README.md.erb index f5b4455..51e244f 100644 --- a/README.md.erb +++ b/README.md.erb @@ -1,42 +1,18 @@ -<%- -def snippet(format, path) - lines = File.new(path).readlines -start = lines.find_index { |line| line.include?('// setup serpapi client') } -if start.nil? - raise "No '// setup serpapi client' marker found in #{path}" -end -stop = lines.find_index do |line| - next false if line.lstrip.start_with?('//') - line.match?(/\bassert(True|NotNull)\s*\(/) -end -if stop.nil? - raise "No assertTrue/assertNotNull found in #{path}" -end -slice = lines[start..stop-1] -slice << "System.out.println(results.toString());" -buf = slice.map { |l| l.gsub(/(^\s\s\s\s)/, '')}.join -buf.gsub!("System.getenv(\"SERPAPI_KEY\")", "\"your_api_key\"") - - %Q(```#{format}\n#{buf}\n```\n\n * source code: [#{path}](https://github.com/serpapi/serpapi-#{format}/blob/master/#{path})) -end --%> - # SerpApi Java Library [![serpapi-java](https://github.com/serpapi/serpapi-java/actions/workflows/gradle.yml/badge.svg)](https://github.com/serpapi/serpapi-java/actions/workflows/gradle.yml) [![JitPack](https://jitpack.io/v/serpapi/serpapi-java.svg)](https://jitpack.io/#serpapi/serpapi-java) -Integrate search data into your Java application. This library is the official wrapper for [SerpApi](https://serpapi.com). - -SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and more. +Integrate search data into your AI workflow, RAG, fine-tuning, or Java application using this official [SerpApi Java SDK](https://serpapi.com/integrations/java). -[The full documentation is available here.](https://serpapi.com/search-api) +[SerpApi](https://serpapi.com/) supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and many more. ## Installation -Using Maven / Gradle. +Installation of the serpapi-java package is done using Maven / Gradle. + +Any new project should include these lines in a `build.gradle` file. -Edit your `build.gradle` file: ```gradle repositories { maven { url "https://jitpack.io" } @@ -47,14 +23,18 @@ dependencies { } ``` -To list all available versions: +To list all available versions see: https://jitpack.io/api/builds/com.github.serpapi/serpapi-java -or you can download the jar file from https://github.com/serpapi/serpapi-java/releases +or you can download the jar file from https://github.com/serpapi/serpapi-java/releases. + +_Note: JitPack builds Maven artifacts from GitHub releases and tags._ + +## Quickstart Tutorial -Note: JitPack builds Maven artifacts from GitHub releases and tags. +[Create a SerpApi account](https://serpapi.com/dashboard) to get your API key, then store it in an environment variable: -## Usage +```export SERPAPI_KEY="your_api_key"``` To try the library quickly, use the demo project: ```bash @@ -62,15 +42,18 @@ git clone https://github.com/serpapi/serpapi-java.git cd serpapi-java/demo make all SERPAPI_KEY='' ``` -Use quotes if your key contains shell-special characters. You need a SerpApi account to obtain a key: https://serpapi.com/dashboard +Use quotes if your key contains shell-special characters. + +The `serpapi-java` package is already installed inside the `build.gradle` file of this cloned `serpapi-java` repository. + +So, in this tutorial, no extra setup is needed. +For future projects please refer to the above provided 'Installation' section. `demo/src/main/java/demo/App.java`: ```java class App { public static void main(String[] args) { String apiKey = System.getenv("SERPAPI_KEY"); - - // set search location String location = "Austin,Texas"; String engine = "google"; System.out.println("find the first coffee shop in " + location + " using " + engine); @@ -78,18 +61,13 @@ class App { Map auth = new HashMap<>(); auth.put("engine", engine); auth.put("api_key", apiKey); + SerpApi serpapi = new SerpApi(auth); - // create client - SerpApi serpapi= new SerpApi(auth); - - // create search parameters Map parameter = new HashMap<>(); parameter.put("q", "Coffee"); parameter.put("location", location); - // perform search try { - // get search results JsonObject data = serpapi.search(parameter); JsonArray organic = data.getAsJsonArray("organic_results"); JsonObject first = organic.get(0).getAsJsonObject(); @@ -103,197 +81,451 @@ class App { } ``` -The [SerpApi.com API Documentation](https://serpapi.com/search-api) contains a list of all the possible parameters that can be passed to the API. +## Features +- Asynchronous searches for submitting non-blocking jobs and retrieving completed results from the Search Archive API +- Search results stored as a [Gson](https://github.com/google/gson) for JSON and returns responses as Gson `JsonObject` / `JsonArray` 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) -## Documentation +## Response Formats -- [SerpApi Search API](https://serpapi.com/search-api) — parameters, engines, and response formats -- After cloning, run `./gradlew javadoc` and open `build/docs/javadoc/index.html` for this library’s Javadoc. +Use `search` for structured results decoded into a `Gson JsonObject / JsonArray`: + +```results = client.search(parameter);``` + +Use `md` for a token-efficient Markdown String optimized for LLMs and AI agents: + +```markdown = client.markdown(parameter);``` + +Use `html` when you need the raw search-engine response: + +```rawHtml = client.html(parameter);``` + +Learn more about [SerpApi Markdown output](https://serpapi.com/markdown-output). + +> A couple of notes: +> - `client` is a `SerpApi` instance you create with your API key, e.g. `SerpApi client = new SerpApi(auth);` where `auth` is a `Map` containing `"api_key"` (and typically `"engine"`). +> - `parameter` is a `Map` with your search parameters (`q`, `location`, etc.). +> - `client.markdown(parameter)` is new as of `serpapi-java` **1.2.0** - make sure your `build.gradle` dependency is at least that version ## Requirements This library uses [Gson](https://github.com/google/gson) for JSON and returns responses as Gson `JsonObject` / `JsonArray`. -**This repository** is built and tested with **JDK 21** and the **Gradle wrapper** (`./gradlew`, currently Gradle 8.5). Use the wrapper so you do not need a separate Gradle install. +**This repository** is built and tested with **JDK 21** and the **Gradle wrapper** (`./gradlew`, currently Gradle 9.1.0). Use the wrapper so you do not need a separate Gradle install. **Consumers** of the JitPack artifact should run a JVM whose version is at least the **bytecode level** of the release you depend on (releases from this branch target **Java 21**). +## Configuration -### Location API +Set defaults when creating a client, then override search parameters in individual calls: ```java -SerpApi serpapi = new SerpApi(); - -Map parameter = new HashMap(); -parameter.put("q", "Austin"); -parameter.put("limit", "3"); -JsonArray location = serpapi.location(parameter); -System.out.println(location.get(0).getAsJsonObject().get("name").getAsString()); -// Prints the first matching name among up to 3 results (see LocationApiTest for a JUnit example). +Map auth = new HashMap<>(); +auth.put("api_key", System.getenv("SERPAPI_KEY")); +auth.put("engine", "google"); +auth.put("hl", "en"); +auth.put("gl", "us"); +SerpApi client = new SerpApi(auth); + +Map parameter = new HashMap<>(); +parameter.put("q", "coffee"); +parameter.put("gl", "gb"); +parameter.put("async", "false"); + +try { + JsonObject results = client.search(parameter); +} catch (SerpApiException e) { + e.printStackTrace(); +} +``` + +| Field | 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. | +| `async` | false | Submits searches without waiting for them to complete. It can be set on the client or per 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 +Search API features non-blocking search using the option: `async=true`. + +- Non-blocking - `async=true` - a single thread can submit many searches without waiting for each one to complete, then collects results later from the Search Archive API. +- Blocking - `async=false` - each search call blocks the calling thread until results are ready. To run searches concurrently, you'd need multiple threads (i.e. through an `ExecutorService`), each holding its own connection open for the duration of its search. This is more I/O-intensive, since concurrency requires as many held-open connections as concurrent searches. + +Here is an example simulation of asynchronous searches using Java: + + ```java +String apiKey = System.getenv("SERPAPI_KEY"); + +Map auth = new HashMap<>(); +auth.put("engine", "google"); +auth.put("api_key", apiKey); +auth.put("async", "true"); +SerpApi client = new SerpApi(auth); + +Queue ids = new LinkedList<>(); + +for (String company : new String[]{"meta", "amazon", "apple", "netflix", "google"}) { + Map parameter = new HashMap<>(); + parameter.put("q", company); + + JsonObject result = client.search(parameter); + ids.add(result.getAsJsonObject("search_metadata").get("id").getAsString()); +} + +System.out.println("waiting 10s for searches to complete..."); +// for production use cases, continuous polling instead of waiting is necessary +Thread.sleep(10000); + +while (!ids.isEmpty()) { + JsonObject archived = client.searchArchive(ids.poll()); + String status = archived.getAsJsonObject("search_metadata").get("status").getAsString(); + String company = archived.getAsJsonObject("search_parameters").get("q").getAsString(); + System.out.println(company + ": " + status); +} ``` -[LocationApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/LocationApiTest.java) +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 a 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 `searchArchive` method blocks until the search results are available. -### Search Archive API +## 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. -Run a search to obtain a `search_id`. ```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_shopping"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -SerpApi serpapi = new SerpApi(auth); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); Map parameter = new HashMap<>(); -parameter.put("q", "Coffee"); -parameter.put("location", "Austin, Texas, United States"); -parameter.put("hl", "en"); -parameter.put("gl", "us"); -parameter.put("google_domain", "google.com"); -parameter.put("safe", "active"); -parameter.put("start", "10"); -parameter.put("device", "desktop"); -JsonObject results = serpapi.search(parameter); +parameter.put("q", "Macbook M4"); + +try { + JsonObject data = client.search(parameter); + JsonArray results = data.getAsJsonArray("shopping_results"); + if (results != null && results.size() > 0) { + JsonObject first = results.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` -Retrieve the same search from the archive: +Source code: [src/test/java/serpapi/example/GoogleShoppingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleShoppingTest.java) + +[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. + ```java -// now search in the archive -String id = results.getAsJsonObject("search_metadata").getAsJsonPrimitive("id").getAsString(); +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_images"; + +Map auth = new HashMap<>(); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); + +Map parameter = new HashMap<>(); +parameter.put("q", "coffee"); -// retrieve search from the archive with speed for free -JsonObject archive = serpapi.searchArchive(id); -System.out.println(archive.toString()); +try { + JsonObject data = client.search(parameter); + JsonArray results = data.getAsJsonArray("images_results"); + if (results != null && results.size() > 0) { + JsonObject first = results.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` -The archived JSON matches the original search result. In tests, the key is supplied via `System.getenv("SERPAPI_KEY")`; see `SerpApiTest.java`. -[SerpApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/SerpApiTest.java) +Source code: [src/test/java/serpapi/example/GoogleImagesTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleImagesTest.java) + +[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 -### Account API +Scrape results from the Google Lens page when performing an image search. The results related to the image could contain visual matches and other data. ```java -Map parameter = new HashMap<>(); -parameter.put("api_key", "your_api_key"); +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_lens"; + +Map auth = new HashMap<>(); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); -SerpApi serpapi = new SerpApi(parameter); -JsonObject account = serpapi.account(); -System.out.println(account.toString()); +Map parameter = new HashMap<>(); +parameter.put("url", "https://i.imgur.com/your_image.png"); + +try { + JsonObject data = client.search(parameter); + JsonArray visualMatches = data.getAsJsonArray("visual_matches"); + System.out.println(visualMatches); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` -it prints your account information. -[AccountApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/AccountApiTest.java) +Source code: [src/test/java/serpapi/example/GoogleLensTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleLensTest.java) + +[See Image API documentation](https://serpapi.com/image-api) · [See Google Lens image upload documentation](https://serpapi.com/google-lens-upload-an-image) -### Markdown output +### Google Trends + +Track search interest over time and compare the popularity of search terms. ```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_trends"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); -auth.put("engine", "google"); -SerpApi serpapi = new SerpApi(auth); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); Map parameter = new HashMap<>(); parameter.put("q", "coffee"); -System.out.println(serpapi.markdown(parameter)); +parameter.put("data_type", "TIMESERIES"); + +try { + JsonObject data = client.search(parameter); + JsonObject interestOverTime = data.getAsJsonObject("interest_over_time"); + + if (interestOverTime != null) { + JsonArray timelineData = interestOverTime.getAsJsonArray("timeline_data"); + + if (timelineData != null && timelineData.size() > 0) { + JsonObject first = timelineData.get(0).getAsJsonObject(); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(first)); + } + } +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} +``` + +Source code: [src/test/java/serpapi/example/GoogleTrendsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleTrendsTest.java) + +[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`._ + +```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_flights"; + +Map auth = new HashMap<>(); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); + +String outboundDate = LocalDate.now().plusDays(7).toString(); +String returnDate = LocalDate.now().plusDays(14).toString(); + +Map parameter = new HashMap<>(); +parameter.put("departure_id", "LAX"); +parameter.put("arrival_id", "AUS"); +parameter.put("outbound_date", outboundDate); +parameter.put("return_date", returnDate); + +try { + JsonObject data = client.search(parameter); + JsonArray bestFlights = data.getAsJsonArray("best_flights"); + //JsonArray otherFlights = data.getAsJsonArray("other_flights"); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(bestFlights)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` -it prints the results as raw markdown, intended for LLM and agent consumption. +Source code: [src/test/java/serpapi/example/GoogleFlightsTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleFlightsTest.java) -[MarkdownApiTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/MarkdownApiTest.java) +[See documentation](https://serpapi.com/google-flights-api) -## Examples in Java +### Google AI Mode API +The Google AI Mode API returns AI-generated answers with structured text blocks, references, images, products, and more. + +```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "google_ai_mode"; -### Search bing -<%= snippet('java', 'src/test/java/serpapi/example/BingTest.java') %> -see: [https://serpapi.com/bing-search-api](https://serpapi.com/bing-search-api) +Map auth = new HashMap<>(); +auth.put("engine", engine); +auth.put("api_key", apiKey); +SerpApi client = new SerpApi(auth); -### Search baidu -<%= snippet('java', 'src/test/java/serpapi/example/BaiduTest.java') %> -see: [https://serpapi.com/baidu-search-api](https://serpapi.com/baidu-search-api) +Map parameter = new HashMap<>(); +parameter.put("q", "best coffee maker"); + +try { + String markdownData = client.markdown(parameter); + System.out.println(markdownData); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} +``` -### Search yahoo -<%= snippet('java', 'src/test/java/serpapi/example/YahooTest.java') %> -see: [https://serpapi.com/yahoo-search-api](https://serpapi.com/yahoo-search-api) +Source code: [src/test/java/serpapi/example/GoogleAIModeTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleAIModeTest.java) -### Search youtube -<%= snippet('java', 'src/test/java/serpapi/example/YoutubeTest.java') %> -see: [https://serpapi.com/youtube-search-api](https://serpapi.com/youtube-search-api) +[See documentation](https://serpapi.com/google-ai-mode-api) -### Search walmart -<%= snippet('java', 'src/test/java/serpapi/example/WalmartTest.java') %> -see: [https://serpapi.com/walmart-search-api](https://serpapi.com/walmart-search-api) +### Bing Search -### Search ebay -<%= snippet('java', 'src/test/java/serpapi/example/EbayTest.java') %> -see: [https://serpapi.com/ebay-search-api](https://serpapi.com/ebay-search-api) +Scrape Bing web search results, including organic results, ads, related searches, and more. -### Search naver -<%= snippet('java', 'src/test/java/serpapi/example/NaverTest.java') %> -see: [https://serpapi.com/naver-search-api](https://serpapi.com/naver-search-api) +```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "bing"; -### Search home depot -<%= snippet('java', 'src/test/java/serpapi/example/HomeDepotTest.java') %> -see: [https://serpapi.com/home-depot-search-api](https://serpapi.com/home-depot-search-api) +Map auth = new HashMap<>(); +auth.put("api_key", apiKey); +auth.put("engine", engine); +SerpApi client = new SerpApi(auth); -### Search apple app store -<%= snippet('java', 'src/test/java/serpapi/example/AppleAppStoreTest.java') %> -see: [https://serpapi.com/apple-app-store](https://serpapi.com/apple-app-store) +Map parameter = new HashMap<>(); +parameter.put("q", "coffee"); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} +``` -### Search duckduckgo -<%= snippet('java', 'src/test/java/serpapi/example/DuckduckgoTest.java') %> -see: [https://serpapi.com/duckduckgo-search-api](https://serpapi.com/duckduckgo-search-api) +Source code: [src/test/java/serpapi/example/BingTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BingTest.java) -### Search google -<%= snippet('java', 'src/test/java/serpapi/example/GoogleTest.java') %> -see: [https://serpapi.com/search-api](https://serpapi.com/search-api) +[See documentation](https://serpapi.com/bing-search-api) -### Search google scholar -<%= snippet('java', 'src/test/java/serpapi/example/GoogleScholarTest.java') %> -see: [https://serpapi.com/google-scholar-api](https://serpapi.com/google-scholar-api) +### DuckDuckGo Search -### Search google autocomplete -<%= snippet('java', 'src/test/java/serpapi/example/GoogleAutocompleteTest.java') %> -see: [https://serpapi.com/google-autocomplete-api](https://serpapi.com/google-autocomplete-api) +Scrape DuckDuckGo search results, including organic results, ads, knowledge graphs, and related searches. -### Search google product ```java -// setup serpapi client +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "duckduckgo"; + Map auth = new HashMap<>(); -auth.put("api_key", "your_api_key"); +auth.put("api_key", apiKey); +auth.put("engine", engine); SerpApi client = new SerpApi(auth); -// run search Map parameter = new HashMap<>(); -parameter.put("engine", "google_product"); parameter.put("q", "coffee"); -parameter.put("product_id", "4887235756540435899"); -JsonObject results = client.search(parameter); -System.out.println(results.toString()); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} +``` + +Source code: [src/test/java/serpapi/example/DuckduckgoTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/DuckduckgoTest.java) + +[See documentation](https://serpapi.com/duckduckgo-search-api) + +### Baidu Search + +Scrape Baidu search results, including organic results, answer boxes, and related searches. + +```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "baidu"; + +Map auth = new HashMap<>(); +auth.put("api_key", apiKey); +auth.put("engine", engine); +SerpApi client = new SerpApi(auth); + +Map parameter = new HashMap<>(); +parameter.put("q", "coffee"); +try { + JsonObject results = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(results)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} ``` - * source code: [src/test/java/serpapi/example/GoogleProductTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/GoogleProductTest.java) +Source code: [src/test/java/serpapi/example/BaiduTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/BaiduTest.java) -see: [https://serpapi.com/google-product-api](https://serpapi.com/google-product-api) +[See documentation](https://serpapi.com/baidu-search-api) -### Search google reverse image -<%= snippet('java', 'src/test/java/serpapi/example/GoogleReverseImageTest.java') %> -see: [https://serpapi.com/google-reverse-image](https://serpapi.com/google-reverse-image) +### Amazon Search -### Search google events -<%= snippet('java', 'src/test/java/serpapi/example/GoogleEventsTest.java') %> -see: [https://serpapi.com/google-events-api](https://serpapi.com/google-events-api) +Scrape Amazon product search results, including product names, prices, ratings, reviews, and availability. -### Search google maps -<%= snippet('java', 'src/test/java/serpapi/example/GoogleMapsTest.java') %> -see: [https://serpapi.com/google-maps-api](https://serpapi.com/google-maps-api) +_Note: The `amazon` engine uses the `k` parameter for a keyword search, not `q`._ -### Search google jobs -<%= snippet('java', 'src/test/java/serpapi/example/GoogleJobsTest.java') %> -see: [https://serpapi.com/google-jobs-api](https://serpapi.com/google-jobs-api) +```java +String apiKey = System.getenv("SERPAPI_KEY"); +String engine = "amazon"; -### Search google play -<%= snippet('java', 'src/test/java/serpapi/example/GooglePlayTest.java') %> -see: [https://serpapi.com/google-play-api](https://serpapi.com/google-play-api) +Map auth = new HashMap<>(); +auth.put("api_key", apiKey); +auth.put("engine", engine); +SerpApi client = new SerpApi(auth); + +Map parameter = new HashMap<>(); +parameter.put("k", "coffee"); +parameter.put("amazon_domain", "amazon.com"); + +try { + JsonObject data = client.search(parameter); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + System.out.println(gson.toJson(data)); +} catch (SerpApiException e) { + e.printStackTrace(); + System.exit(1); +} +``` +Source code: [src/test/java/serpapi/example/AmazonSearchTest.java](https://github.com/serpapi/serpapi-java/blob/master/src/test/java/serpapi/example/AmazonSearchTest.java) -### Search google images -<%= snippet('java', 'src/test/java/serpapi/example/GoogleImagesTest.java') %> -see: [https://serpapi.com/images-results](https://serpapi.com/images-results) +[See documentation](https://serpapi.com/amazon-search-api) ## Migration from google-search-results-java @@ -312,17 +544,17 @@ implementation 'com.github.serpapi:serpapi-java:1.2.0' ### Class and method renames -| Old (`google-search-results-java`) | New (`serpapi-java`) | -|------------------------------------|----------------------| -| `GoogleSearch` | `SerpApi` | -| `SerpApiSearch` | `SerpApi` | -| `client.getJson()` | `client.search(parameter)` | -| `client.getHtml()` | `client.html(parameter)` | -| — | `client.markdown(parameter)` — new in 1.2.0, see [Markdown output](#markdown-output) | -| `client.getSearchArchive(id)` | `client.searchArchive(id)` | -| `client.getAccount()` | `client.account()` | -| `client.getLocation(parameter)` | `client.location(parameter)` | -| `SerpApiSearchException` | `SerpApiException` | +| Old (`google-search-results-java`) | New (`serpapi-java`) | +| ---------------------------------- | ------------------------------------------------------------------------------------ | +| `GoogleSearch` | `SerpApi` | +| `SerpApiSearch` | `SerpApi` | +| `client.getJson()` | `client.search(parameter)` | +| `client.getHtml()` | `client.html(parameter)` | +| — | `client.markdown(parameter)` — new in 1.2.0 | +| `client.getSearchArchive(id)` | `client.searchArchive(id)` | +| `client.getAccount()` | `client.account()` | +| `client.getLocation(parameter)` | `client.location(parameter)` | +| `SerpApiSearchException` | `SerpApiException` | ### Example @@ -345,37 +577,15 @@ parameter.put("engine", "google"); JsonObject results = client.search(parameter); ``` -### Contributing - -We use JUnit, **GitHub Actions** (see [workflow](https://github.com/serpapi/serpapi-java/blob/master/.github/workflows/gradle.yml)), and Gradle. - -Run the full test suite locally (integration tests call the live API when a key is present): - -```bash -export SERPAPI_KEY='your_key' # optional: without it, many tests skip; some tests require the key and will fail if unset -./gradlew test -``` - -Regenerate `README.md` from the template after editing examples: - -```bash -make readme # requires Ruby `erb` -``` - -#### How to build from source +## Documentation -Clone the repository: -```bash -git clone https://github.com/serpapi/serpapi-java.git -cd serpapi-java -``` +SerpApi supports Google Search, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, Apple App Store, and many other APIs. Browse the [SerpApi](https://serpapi.com/search-api) documentation to find supported APIs and parameters, or use the [Playground](https://serpapi.com/playground) to build a request and generate code. -Build (use the wrapper): -```bash -./gradlew build -``` +Additional SDK resources: -The main library JAR is under `build/libs/` (for example `serpapi-1.1.0.jar`, name follows `version` in `build.gradle`). Copy it into your project’s `lib/` directory if you are not using Maven/Gradle dependency resolution. +- [Java SDK integration page](https://serpapi.com/integrations/java) +- [Java package](https://github.com/serpapi/serpapi-java) +- [SerpApi status](https://serpapi.com/status) ## TLS / HTTPS and older JVMs ### Symptom @@ -398,15 +608,12 @@ java -version On Windows, install a current JDK from your vendor and point `JAVA_HOME` at it. -### Inspiration +## Inspiration * https://www.baeldung.com/java-http-request * https://github.com/google/gson - -## License -MIT license -## Changelog -- 1.2.0 — Add markdown support, improve error handling if corrupt data received -- 1.1.0 — Java 21, Gradle 8.x; ongoing API and example updates -- 1.0.0 — Revisit API naming and align the client with serpapi.com +## Contributing + +Contributions are welcome. Make sure to read our [contributing guide](https://github.com/serpapi/serpapi-java/blob/master/CONTRIBUTING.md) +© 2026 [SerpApi](https://serpapi.com/) \ No newline at end of file diff --git a/src/test/java/serpapi/example/AmazonSearchTest.java b/src/test/java/serpapi/example/AmazonSearchTest.java new file mode 100644 index 0000000..e1a87ea --- /dev/null +++ b/src/test/java/serpapi/example/AmazonSearchTest.java @@ -0,0 +1,37 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Amazon Search has organic results + */ +public class AmazonSearchTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "amazon"); + parameter.put("k", "coffee"); + parameter.put("amazon_domain", "amazon.com"); + JsonObject results = client.search(parameter); + assertTrue(results.getAsJsonArray("organic_results").size() > 1); + } + +} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleAIModeTest.java b/src/test/java/serpapi/example/GoogleAIModeTest.java new file mode 100644 index 0000000..5a597bd --- /dev/null +++ b/src/test/java/serpapi/example/GoogleAIModeTest.java @@ -0,0 +1,36 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Google AI Mode has a text_blocks response + */ +public class GoogleAIModeTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "google_ai_mode"); + parameter.put("q", "best coffee maker"); + JsonObject results = client.search(parameter); + assertTrue(results.getAsJsonArray("text_blocks").size() > 0); + } + +} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleFlightsTest.java b/src/test/java/serpapi/example/GoogleFlightsTest.java new file mode 100644 index 0000000..005f847 --- /dev/null +++ b/src/test/java/serpapi/example/GoogleFlightsTest.java @@ -0,0 +1,52 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import com.google.gson.JsonArray; +import org.junit.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Google Flights has best or other flights + */ +public class GoogleFlightsTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + DateTimeFormatter fmt = DateTimeFormatter.ISO_LOCAL_DATE; + String outboundDate = LocalDate.now().plusDays(30).format(fmt); + String returnDate = LocalDate.now().plusDays(37).format(fmt); + + Map parameter = new HashMap<>(); + parameter.put("engine", "google_flights"); + parameter.put("departure_id", "LAX"); + parameter.put("arrival_id", "AUS"); + parameter.put("outbound_date", outboundDate); + parameter.put("return_date", returnDate); + JsonObject results = client.search(parameter); + + JsonArray bestFlights = results.getAsJsonArray("best_flights"); + JsonArray otherFlights = results.getAsJsonArray("other_flights"); + JsonArray flights = (bestFlights != null && bestFlights.size() > 0) ? bestFlights : otherFlights; + + assertNotNull(flights); + assertTrue(flights.size() > 0); + } + +} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleJobsTest.java b/src/test/java/serpapi/example/GoogleJobsTest.java index c44c2f7..d946106 100644 --- a/src/test/java/serpapi/example/GoogleJobsTest.java +++ b/src/test/java/serpapi/example/GoogleJobsTest.java @@ -2,7 +2,7 @@ import serpapi.*; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; +import org.junit.Ignore; import org.junit.Test; import java.util.HashMap; @@ -10,11 +10,9 @@ import static org.junit.Assert.*; -/** - * Test main class - */ public class GoogleJobsTest { + @Ignore("google_jobs engine intermittently returns invalid results; not a client bug") @Test public void search() throws SerpApiException { // skip test if no api_key provided @@ -29,9 +27,9 @@ public void search() throws SerpApiException { // run search Map parameter = new HashMap<>(); parameter.put("engine", "google_jobs"); - parameter.put("q", "coffee"); + parameter.put("q", "barista"); + parameter.put("location", "Austin, Texas, United States"); JsonObject results = client.search(parameter); assertTrue(results.getAsJsonArray("jobs_results").size() > 5); } - } \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleLensTest.java b/src/test/java/serpapi/example/GoogleLensTest.java new file mode 100644 index 0000000..4a9a4f0 --- /dev/null +++ b/src/test/java/serpapi/example/GoogleLensTest.java @@ -0,0 +1,36 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Google Lens has visual matches + */ +public class GoogleLensTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "google_lens"); + parameter.put("url", "https://i.imgur.com/HBrB8p0.png"); + JsonObject results = client.search(parameter); + assertTrue(results.getAsJsonArray("visual_matches").size() > 1); + } + +} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleShoppingTest.java b/src/test/java/serpapi/example/GoogleShoppingTest.java new file mode 100644 index 0000000..81c5fc0 --- /dev/null +++ b/src/test/java/serpapi/example/GoogleShoppingTest.java @@ -0,0 +1,36 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Google Shopping has shopping results + */ +public class GoogleShoppingTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("API_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "google_shopping"); + parameter.put("q", "Macbook M4"); + JsonObject results = client.search(parameter); + assertTrue(results.getAsJsonArray("shopping_results").size() > 1); + } + +} \ No newline at end of file diff --git a/src/test/java/serpapi/example/GoogleTest.java b/src/test/java/serpapi/example/GoogleTest.java index 08d050d..ba26e27 100644 --- a/src/test/java/serpapi/example/GoogleTest.java +++ b/src/test/java/serpapi/example/GoogleTest.java @@ -2,7 +2,6 @@ import serpapi.*; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import org.junit.Test; import java.util.HashMap; diff --git a/src/test/java/serpapi/example/GoogleTrendsTest.java b/src/test/java/serpapi/example/GoogleTrendsTest.java new file mode 100644 index 0000000..f0b63e3 --- /dev/null +++ b/src/test/java/serpapi/example/GoogleTrendsTest.java @@ -0,0 +1,43 @@ +package serpapi.example; +import serpapi.*; + +import com.google.gson.JsonObject; +import com.google.gson.JsonArray; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Test Google Trends has timeline data + */ +public class GoogleTrendsTest { + + @Test + public void search() throws SerpApiException { + // skip test if no api_key provided + if(System.getenv("SERPAPI_KEY") == null) + return; + + // setup serpapi client + Map auth = new HashMap<>(); + auth.put("api_key", System.getenv("SERPAPI_KEY")); + SerpApi client = new SerpApi(auth); + + // run search + Map parameter = new HashMap<>(); + parameter.put("engine", "google_trends"); + parameter.put("q", "coffee"); + parameter.put("data_type", "TIMESERIES"); + JsonObject results = client.search(parameter); + + JsonObject interestOverTime = results.getAsJsonObject("interest_over_time"); + assertNotNull(interestOverTime); + + JsonArray timelineData = interestOverTime.getAsJsonArray("timeline_data"); + assertTrue(timelineData.size() > 1); + } + +} \ No newline at end of file