New to Rust? Grab our free Rust for Beginners eBook Get it free →
Google Search Engine Data: Query Zenserp API

An app that stores Google results needs a response its code can inspect without parsing a results page. Zenserp returns Google search results as JSON, which Node.js can parse into named fields.
This article explains the request setup and the checks to make when a request fails.
TL;DR
Zenserp returns Google search results as JSON from its search endpoint, so a Node.js app can read fields instead of parsing a results page. Send a GET request with a query and keep the API key in an environment variable.
Use the apikey header instead of placing a secret in the URL because URLs can be copied into logs or history.
- Use the /api/v2/search endpoint with the apikey request header.
- Set location and language parameters to match the search you want.
- Check the HTTP status before parsing the JSON response.
What Is Zenserp and Google Search Data?
A search engine results page, or SERP, is what Google returns for a query. Zenserp provides an API that returns data for a search query and its context.
A single SERP response answers one query in its supplied context. A ranking dataset can collect records across queries and dates. Use an API for a targeted application request or a dataset for broader analysis.
JSON is text organized as named fields and values. Node parses it into an object so an application can read a result title, URL or another field.
| Example field | What it represents | How an app can use it |
|---|---|---|
| organic | An array of organic search results in the vendor’s example | Loop through entries after checking the response shape |
| position | The displayed position of one result | Store the position with the query and date |
| title | The result’s displayed title | Show a label or compare titles |
| url | The result destination in the example | Link to the result or save its destination |
| description | Example summary text for a result | Show a snippet or retain it with the record |
I used the vendor homepage’s public response example to build the field table. Those names are illustrative, not live search results. Use it as a parser template because actual fields can vary with the query and search features.
How to Request Google Search Data with Zenserp in Node.js
Build the query URL before adding credentials because it makes the search context explicit before authentication.
Step 1: Check that Node provides fetch
I checked Node v26.7.0 in this workspace. Global fetch is available.
if (typeof fetch !== "function") {
console.error("This Node runtime does not expose global fetch.");
process.exit(1);
}
console.log(`Node ${process.version}: global fetch is available.`);
Command: node node_check.js
Node v26.7.0: global fetch is available.
[exit 0]

Step 2: Build the query URL
I ran the URL builder for the sample query and confirmed it printed an encoded URL without sending a search request. Choose context settings from the table, then hold the query constant when comparing them.
const params = new URLSearchParams({
q: "Pied Piper",
location: "New York",
gl: "us",
hl: "en",
device: "desktop",
num: "10",
});
const url = new URL("https://app.zenserp.com/api/v2/search");
url.search = params.toString();
console.log(url.toString());
Command: node zenserp_query.js
https://app.zenserp.com/api/v2/search?q=Pied+Piper&location=New+York&gl=us&hl=en&device=desktop&num=10
[exit 0]

| Parameter | Purpose | Example |
|---|---|---|
| q | Search phrase | Pied Piper |
| location | Named place for localized results | New York |
| gl | Country context | us |
| hl | Interface language | en |
| device | Device context | desktop |
| num | Requested result count, up to 100 | 10 |
| start | Offset for a later results page | Use the documented offset |
Use start to fetch a later page. Verify the accepted offset in current docs. Keep the query and search context fixed across pages, then store each offset with its response so an application can assemble the requested range.
Step 3: Send the request with the API key
Get an API key from Zenserp and make it available to the Node process as ZENSERP_API_KEY. The current migration guide uses the apikey header, so this program does not put the secret in its source code or request URL.
const apiKey = process.env.ZENSERP_API_KEY;
if (!apiKey) {
console.log("ZENSERP_API_KEY is not set; no request sent.");
process.exit(0);
}
const url = new URL("https://app.zenserp.com/api/v2/search");
url.searchParams.set("q", "Pied Piper");
const response = await fetch(url, {
headers: { apikey: apiKey },
});
const body = await response.text();
if (!response.ok) {
console.error(`Request failed: HTTP ${response.status}`);
console.error(body);
process.exitCode = 1;
} else {
const data = JSON.parse(body);
console.log(JSON.stringify(data, null, 2));
}
Command: node zenserp_search.js
ZENSERP_API_KEY is not set; no request sent.
[exit 0]

I ran the request file with ZENSERP_API_KEY unset. It stopped before fetch and printed the message above.
With a key present, the program sends a GET request with the key in the apikey header and reads the body once as text. It checks response.ok. On success it parses JSON, and on an HTTP error it prints the status and body.
What Should You Check When a Zenserp Request Fails?
Use the table to choose the next check because each error points to a different request layer.
| What you see | What to check | Next action |
|---|---|---|
| The program prints a missing-key message | The environment variable is empty or unavailable to Node | Set the secret in the environment that launches Node, then rerun the file |
| HTTP error status | Read the returned status and body without printing your key | Check the credential or request before retrying |
| No HTTP status appears | Fetch threw before a response arrived | Catch the transport exception separately |
| The response succeeds but a field is missing | Compare the actual JSON with the fields your code expects | Handle optional data instead of assuming every result has the same shape |
| Results use the wrong search context | Review the geographic and language settings in the request | Record those inputs with the response before comparing results |
A blocked Google page is one reason developers look for a results API, but a service can still reject a request when the credentials or query are invalid. Treat this API as a documented provider interface and follow its terms.
- Confirm the environment variable exists before starting Node.
- Read the HTTP status and response body without exposing the key.
- Keep the status code with a retry so its outcome remains visible.
Zenserp’s current pricing page says successful requests are billed. Estimate a recurring workflow by its query, context and page count, then compare expected call volume with the current plan details.
Conclusion: Start with a Reproducible Search Request
Start with one query and explicit context, then add result fields after an authenticated request returns data.
For a broader Node request example, see CodeForGeek’s REST API guide. If your task is scraping page HTML rather than retrieving Google search results, the separate ZenScrape article covers that different workflow.
- Zenserp API migration guide for endpoint and parameter details.
- Zenserp pricing and current plan limits before production use.
FAQ
Use the current API documentation for request details and the live pricing page for billing because both can change.
How do I keep the Zenserp API key out of my Node.js file?
Read it from an environment variable and pass it in the apikey request header. Do not commit the key or place it in a shared URL.
Which Zenserp parameter changes the search location?
Use location for a named place. The gl parameter supplies country context, while hl supplies language context. Check the migration guide for current accepted values.
Does Zenserp bill every request?
Zenserp’s current pricing page says successful requests are billed. Review the current plan details before relying on that for a specific error or quota case.




