GridPanel has one API you can use:
Below you will find information on how to use and make the most out of these APIs yourself.
All requests, except when explicitly mentioned, to both GridPanel APIs are authenticated using your private API key.
To get access to your API key, create an account and confirm your email address. You can do this here
Get information about the user this API key belongs to.
curl 'https://gridpanel.net/api/user?api_key=API_KEY'
import requests
params = {
'api_key': 'API_KEY',
}
response = requests.get('https://gridpanel.net/api/user', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/user')
params = {
:api_key => 'API_KEY',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/user?api_key=API_KEY", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/user?api_key=API_KEY');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/user?api_key=API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/user?api_key=API_KEY');
{
"user": {
"first_name": "Bob",
"last_name": "Marley",
"email": "bob@example.com",
"gbp_balance_in_pence": 10000
}
}
Our mobile proxy API enables you to: rotate your proxies, get information regarding your usage and your orders in general.
Please note, in order to use the proxy endpoints below, you will need to have an active proxy order on your account.
You can order your GridPanel mobile proxies here.
This endpoint allows you to rotate the IP of your mobile proxy.
Please note that this endpoint does not require your api_key as a parameter.
When you call this endpoint, it will take your proxy down for 20-40 seconds in order for us to get you a new IP address. This is because rotation involves taking the device offline then online again in quick succession. If you have a 5G proxy, it will take your proxy down for around 5-10 seconds as the process is much faster here.
name [type] (default_value) | Description |
---|---|
token [string] (required) |
This is your rotation token, you will be given one per order and can find it on your manage order page.
|
curl 'https://gridpanel.net/api/reboot?token=MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi'
import requests
params = {
'token': 'MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi',
}
response = requests.get('https://gridpanel.net/api/reboot', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/reboot')
params = {
:token => 'MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/reboot?token=MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/reboot?token=MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/reboot?token=MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/reboot?token=MsIzNSwwIWE1YjnmMC03Yzk2LTRlY2QtOTVhOC1iNDI1ZWo3MTbzOGi');
In the case of a successful rotation you will receive the following response.
{
"success": true
}
If you attempt to rotate to frequently, in that you rotate faster than you orders minimum rotation time, you will receive the following response.
{
"success": false,
"reason": "too_frequent"
}
Get all proxy orders in your account
curl 'https://gridpanel.net/api/proxies?api_key=API_KEY'
import requests
params = {
'api_key': 'API_KEY',
}
response = requests.get('https://gridpanel.net/api/proxies', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/proxies')
params = {
:api_key => 'API_KEY',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/proxies?api_key=API_KEY", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/proxies?api_key=API_KEY');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/proxies?api_key=API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/proxies?api_key=API_KEY');
{
"orders": {
"10123": {
"port": 10123,
"status": "active",
"expiry_date": "2023-03-30T00:00:00Z",
"plan": "5G Mobile Proxies",
"duration": "Monthly",
"auto_renew": true,
"auto_rotate": false,
"auto_rotate_seconds": null,
"last_reboot": "2023-03-04T12:34:56Z",
"minimum_rotation_time_seconds": 300,
"gateway_ip": "192.168.1.1",
"username": "username",
"password": "password",
"reboot_url": "https://gridpanel.net/api/reboot?token=1234",
"reboot_token": "1234",
"connection_string": "username:password@192.168.1.1:10123",
"network": "THREE",
"location": "LONDON",
},
"10124": {
"port": 10124,
"status": "active",
"expiry_date": "2023-03-30T00:00:00Z",
"plan": "4G Mobile Proxies",
"duration": "Monthly",
"auto_renew": true,
"auto_rotate": false,
"auto_rotate_seconds": null,
"last_reboot": "2023-03-06T12:00:00Z",
"minimum_rotation_time_seconds": 300,
"gateway_ip": "192.168.1.1",
"username": "username",
"password": "password",
"reboot_url": "https://gridpanel.net/api/reboot?token=1235",
"reboot_token": "1235",
"connection_string": "username:password@192.168.1.1:10124",
"network": "EE",
"location": "LONDON",
}
}
}
Returns daily statistics (such as bandwidth usage) for one or more proxies, across a date range.
name [type] (default_value) | Description |
---|---|
ports [string] (required) |
Proxy port(s) to query for (comma-separated) e.g. 10123,10124
|
start [string] (required) |
Date to query from in YYYY-MM-DD format e.g. 2023-01-01
|
end [string] (required) |
Date to query to in YYYY-MM-DD format e.g. 2023-01-01. Must be within 31 days of start but more than 48 hours before the time of request.
|
curl 'https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04'
import requests
response = requests.get(
'https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04',
)
require 'net/http'
uri = URI('https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04')
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/statistics?api_key=API_KEY&ports=10123,10124&start=2023-03-01&end=2023-03-04');
{
"results": {
"10123": [
{
"date": "2023-03-04",
"used_bytes": 11111111111
},
{
"date": "2023-03-03",
"used_bytes": 22222222222
},
{
"date": "2023-03-02",
"used_bytes": 33333333333
},
{
"date": "2023-03-01",
"used_bytes": 44444444444
}
],
"10124": [
{
"date": "2023-03-04",
"used_bytes": 55555555555
},
{
"date": "2023-03-03",
"used_bytes": 66666666666
},
{
"date": "2023-03-02",
"used_bytes": 77777777777
},
{
"date": "2023-03-01",
"used_bytes": 88888888888
}
]
}
}
GridPanel's scraping API is the easiest scraping API available to use on the web.
To scrape any web page, you need two things:
The following is an example snippet of a simple
GET
API call to scrape the URL defined in the query string
variable
YOUR-URL
:
curl 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL'
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL');
The API will then respond with the raw HTML content of the target URL:
<html>
<head>
...
</head>
<body>
...
</body>
</html>
Be aware of the maximum 30-second timeout when your code calls the API
Headers and cookies returned by the target website are prefixed with
Spb-
(for Scraping browser)
Here is the list of the different parameters you can use with GridPanel's HTML API.
name [type] (default_value) | Description |
---|---|
api_key [string] (required) |
Your API key Get your API key
|
url [string] (required) |
The URL of the page you want to scrape
|
country_code [string] ("") |
Geolocation, either UK or US
|
extract_rules [[stringified JSON]] ("") |
Data extraction from CSS selectors
|
js_scenario [[stringified JSON]] ({}) |
JavaScript scenario to execute
|
json_response [bool] (false) |
Wrap the response in JSON
|
screenshot [boolean] (false) |
Return a screenshot of the page you want to scrape
|
timeout [integer] (14000) |
Timeout for your requests
|
wait [integer] (0) |
Additional time in ms for JavaScript to render
|
wait_browser [string] (domcontentloaded) |
Wait until certain browser conditions are met before returning the response
|
wait_for [string] ("") |
CSS/XPath selector to wait for in the DOM
|
This parameter is the full URL including the protocol (with
http/https
) of the page to extract data from.
You must encode your URL. For example, the
+
character is encoded to
%20
. Consult your programming language documentation for functions that encode URLs.
Alternatively you can encode/decode urls using this tool: https://meyerweb.com/eric/tools/dencoder/
We have provided a number of examples for some languages below:
p = URI::Parser.new
p.escape("YOUR-URL")
sudo apt-get install gridsite-clients
urlencode "YOUR URL"
import urllib.parse
encoded_url = urllib.parse.quote("YOUR URL")
<?php
$url_encoded = urlencode("YOUR URL");
?>
String encoded_url = URLEncoder.encode("YOUR URL", "UTF-8");
package main
import (
"net/url"
)
func main() {
encoded_url := url.QueryEscape("YOUR URL")
}
encoded_url = encodeURIComponent("YOUR URL")
Most websites take some time to fully render their full content. Using the wait parameter you can tell GridPanel to wait before it returns the fully rendered HTML.
The wait parameter can be a value in milliseconds between 0 and 35000.
Below you can see an example where we are waiting 10000ms (10 seconds) for the page to load before we return the HTML.
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait=10000"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'wait': '10000',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:wait => '10000',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait=10000", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait=10000');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait=10000"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait=10000');
Instead of waiting a fixed amount of time, you might just want to wait for a particular element to appear in the DOM before returning the HTML.
You can utilise the wait_for parameter to pass a CSS/XPath selector to wait for before returning any HTML.
Below you can see an example of us waiting for the div element with a class value of a-loading-div, therefore we can use wait_for=.a-loading-div
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_for=.a-loading-div"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'wait_for': '.a-loading-div',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:wait_for => '.a-loading-div',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_for=.a-loading-div", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_for=.a-loading-div');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_for=.a-loading-div"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_for=.a-loading-div');
Instead of waiting for a specific time period, or for an element to appear, you can wait until specific network conditions have been met.
This parameter can take one of 4 different values:
Below you can see an example where we are waiting for the DOM to load by passing wait_browser=domcontentloaded.
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_browser=domcontentloaded"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'wait_browser': 'domcontentloaded',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:wait_browser => 'domcontentloaded',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_browser=domcontentloaded", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_browser=domcontentloaded');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_browser=domcontentloaded"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&wait_browser=domcontentloaded');
If you need to extract any data from the pages you scrape, and don't want to process any HTML on your side, you can take advantage of our extraction rules.
These rules are passed through the extract_rules parameter and use the following syntax:
{ "key_name": "css_or_xpath_selector" }
For example, if you are looking to extract the title, and subtitle of a blog post you will need to use rules that look like the following:
{
"title": "h1",
"subtitle": "#subtitle"
}
This will then return the following JSON response:
{
"title": "Your blog title",
"subtitle": "Your blog subtitle"
}
It's important to note that these rules are JSON formatted and therefore need to be stringified when you pass them with your requests. You can see an example request here:
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&extract_rules=%7B%22title%22%3A+%22h1%22%2C+%22subtitle%22%3A+%22%23subtitle%22%7D"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'extract_rules': '{"title": "h1", "subtitle": "#subtitle"}',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:extract_rules => '{"title": "h1", "subtitle": "#subtitle"}',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&extract_rules=%7B%22title%22%3A+%22h1%22%2C+%22subtitle%22%3A+%22%23subtitle%22%7D", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&extract_rules=%7B%22title%22%3A+%22h1%22%2C+%22subtitle%22%3A+%22%23subtitle%22%7D');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&extract_rules=%7B%22title%22%3A+%22h1%22%2C+%22subtitle%22%3A+%22%23subtitle%22%7D"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&extract_rules=%7B%22title%22%3A+%22h1%22%2C+%22subtitle%22%3A+%22%23subtitle%22%7D');
To interact with pages you want to scrape before we return the HTML you can add a JavaScript scenario to your API calls.
For example, to click a button, you can use the following scenario:
{
"instructions": [
{ "click": "#buttonId"}
]
}
This will result with the following API call:
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'js_scenario': '{"instructions": [{"click": "#buttonId"}]}',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:js_scenario => '{"instructions": [{"click": "#buttonId"}]}',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&js_scenario=%7B%22instructions%22%3A+%5B%7B%22click%22%3A+%22%23buttonId%22%7D%5D%7D');
Again please note that the JavaScript scenario parameter is JSON formatted, which means you need to stringify it when you pass it to your API requests.
Each scenario can have multiple instructions, and they will be executed in the order you send them before returning the HTML of the page.
The supported instructions are as follows:
{
"instructions": [
{"click": "#buttonId"}, // Click a button
{"wait": 1000}, // Wait a fixed duration in ms
{"wait_for": #a_div}, // Wait for a specific element
{"wait_for_and_click": #a_div}, // Wait for an element and click it
{"scroll_x": 1000}, // Scroll the screen in the horizontal axis, in px
{"scroll_y": 1000}, // Scroll the screen in the vertical axis, in px
{"fill": ["#input_1", "value_1"]}, // Fill in some input
{"evaluate": "console.log(123)", // Evaluate custom javascript code
{"infinite_scroll": // Scroll the page until end
{
"max_count": 0, // Max number to scroll, 0 is forever
"delay": 1000, // Delay between every scroll in ms
"end_click": { "selector": "#button_id" } // Click a button when the end of the page is reached
}
}
]
}
If an instruction you need is not supported, you can use the evaluate instruction to run any JavaScript code that you need.
If you want your response format to be in JSON and you want to intercept the responses of XHR/Ajax requests you can use the json_response parameter.
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&json_response=true"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'json_response': 'true',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:json_response => 'true',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&json_response=true", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&json_response=true');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&json_response=true"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&json_response=true');
You will receive a response that looks like the following:
{
# Headers sent by the server
"headers": {
"Date": "Fri, 16 Apr 2021 15:03:54 GMT",
...
"Access-Control-Allow-Credentials": "true"
},
# Cost of your request
"cost": 1,
# Initial status code of the server
"initial-status-code": 200,
# Resolved URL (following redirection)
"resolved-url": "https://httpbin.org/",
# Type of the response "html" or "json" or "b64_bytes" for file, image, pdf,...
"type": "html",
# Content of the answer. Content will be base 64 encoded if is a file, image, pdf,...
"body": "<html>... </body>"
# base 64 encoded screenshot of the page, if screenshot=true is used
"screenshot": "b0918...aef",
# Cookies sent back by the server
"cookies": [
{
"name": "cookie_name",
"value": "cookie_value",
"domain": "test.com",
...
},
...
],
# Results of the JS scenario "evaluate" instructions
"evaluate_results": [...]
# Content and source of iframes in the page
"iframes": [
{
"content": "<html>... </body>",
"src": "https://site.com/iframe"
},
...
],
# XHR / Ajax requests sent by the browser
"xhr": [
{
# URL
"url": "https://",
# status code of the server
"status_code": 200,
# Method of the request
"method": "POST",
# Headers of the XHR / Ajax request
"headers": {
"pragma": "no-cache",
...
},
# Response of the XHR / Ajax request
"body": "2d,x"
},
...
],
# js_scenario detailed report ( only useful if js_scenario=...)
"js_scenario_report": {
"task_executed": 1,
"task_failure": 0,
"task_success": 1,
"tasks": [
{
"duration": 3.042,
"params": 3000,
"success": true,
"task": "wait"
}
],
"total_duration": 3.042
},
# Metada / Schema data
"metadata": {
"microdata": ...,
"json-ld": ...,
}
}
If you require a screenshot of the page that you want to scrape, you can use the screenshot parameter.
Your response will then contain a screenshot key where the value is the screenshot data in base64.
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&screenshot=true" > ./screenshot.png
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'screenshot': 'true',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:screenshot => 'true',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&screenshot=true", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&screenshot=true');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&screenshot=true"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&screenshot=true');
You are also able to chose the proxy location using the country_code parameter.
For example to use proxies from the United Kingdom you need to set country_code=uk
curl "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&country_code=us"
import requests
params = {
'api_key': 'API_KEY',
'url': 'YOUR-URL',
'country_code': 'us',
}
response = requests.get('https://gridpanel.net/api/scrape', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape')
params = {
:api_key => 'API_KEY',
:url => 'YOUR-URL',
:country_code => 'us',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&country_code=us", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&country_code=us');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&country_code=us"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape?api_key=API_KEY&url=YOUR-URL&country_code=us');
Allows you to programmatically monitor scrape consumption.
Results are available in real time, and will not increase your request concurrency and will not cost scrapes.
curl 'https://gridpanel.net/api/scrape/usage?api_key=API_KEY'
import requests
params = {
'api_key': 'API_KEY',
}
response = requests.get('https://gridpanel.net/api/scrape/usage', params=params)
require 'net/http'
uri = URI('https://gridpanel.net/api/scrape/usage')
params = {
:api_key => 'API_KEY',
}
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://gridpanel.net/api/scrape/usage?api_key=API_KEY", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s
", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gridpanel.net/api/scrape/usage?api_key=API_KEY');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
curl_close($ch);
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://gridpanel.net/api/scrape/usage?api_key=API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
fetch('https://gridpanel.net/api/scrape/usage?api_key=API_KEY');
{
"result": {
"max_api_scrapes": 100000,
"used_api_scrapes": 301,
"renewal_date": "Free Trial"
}
Every GridPanel plan will provide you a certain number of API scrapes per month.
We want to keep our pricing as simple and as transparent as possible.
We only charge you for successful scrapes (2XX,4XX HTTP responses), and each scrape costs the exact same. No surprises.