PHP wrapper for the WebShare Proxy API with rate-limit retries, GET response caching, filtering, pagination iterators, and typed request helpers.
Domain terms: see CONTEXT.md.
- PHP >= 8.3
- Composer
composer require devcraft/webshare-io-api-wrapperexport API_KEY="your_webshare_api_key"Or .env:
API_KEY=your_webshare_api_key
API_URL=https://proxy.webshare.io/api/
API_VERSION=v2
CACHE_ENABLED=1
CACHE_LIFETIME=3600
CACHE_DIRECTORY=./cache
ITERATE_MAX_PAGES=100
DEBUG=0
<?php
require_once 'vendor/autoload.php';
use Devcraft\Webshare\Classes\App;
use Devcraft\Webshare\Enums\FilterOperator;
App::init();
/** @var \Devcraft\Webshare\Requests\ProxyRequest $proxies */
$proxies = App::Requests('Proxy');
$proxies->query()
->withFilter('mode', 'direct')
->withPageSize(25)
->withFilter('country_code', ['US', 'DE'], FilterOperator::IN);
$list = $proxies->getList();
foreach ($proxies->iterate() as $proxy) {
echo $proxy->getConnectionString(backbone: true), "\n";
}App::Client() returns the shared HTTP client. App::Requests('Profile'|'Notification'|…) auto-discovers request classes.
| App::Requests key | Coverage |
|---|---|
Proxy |
list, iterate, download, refresh |
Profile |
profile + preferences |
Notification |
list/retrieve/dismiss/restore |
ProxyReplacement |
list/retrieve/create (v3) |
ReplacedProxy |
list/download |
ProxyConfig |
config/status/listStats/update (v3) |
IpAuthorization |
list/iterate/CRUD + whatsMyIp |
ProxyStats |
list/aggregate/activities/download |
DownloadToken |
get/reset token by scope |
ApiKey |
list/iterate/CRUD |
SubUser |
list/iterate/CRUD/refresh + masqueradeAs() |
Proxy Connection is not a REST resource — use Proxy::getConnectionString() (backbone/direct). See CONTEXT.md.
Successful GET responses are cached (CACHE_LIFETIME). Mutations invalidate the resource tag. Paths containing /download/ are never cached. Bypass with forceRefresh: true on request() / Client::send(), or CACHE_ENABLED=0.
$proxies->query()
->withFilter('country_code', ['US', 'DE'], FilterOperator::IN)
->withFilter('created_at', '2024-01-01', FilterOperator::GT)
->withOrderBy('-created_at', 'country_code')
->withSearch('residential');| Operator | API syntax |
|---|---|
EQUAL |
?field=value |
IN |
?field__in=a,b |
GT / LT |
?field__gt= / __lt= |
CONTAINS |
?field__contains= |
Manual pages via withPage / withStartingAfter, or iterate() / PageIterator::items() (default max pages from ITERATE_MAX_PAGES, default 100).
App::Requests('SubUser')->masqueradeAs(7);
// subsequent Client calls send X-Subuser: 7
App::Requests('SubUser')->masqueradeAs(null);use Devcraft\Webshare\Exceptions\ApiException;
use Devcraft\Webshare\Exceptions\RateLimitException;
try {
App::Requests('Proxy')->query()->withFilter('mode', 'direct');
App::Requests('Proxy')->getList();
} catch (RateLimitException $e) {
echo "Retry after {$e->retryAfterSeconds}s\n";
} catch (ApiException $e) {
foreach ($e->getValidationErrors() as $field => $errors) {
foreach ($errors as $error) {
echo "$field: {$error['message']}\n";
}
}
}429/5xx: up to 3 retries with exponential backoff; Retry-After preferred; x-ratelimit-reset timestamps are converted and clamped (1–120s).
AGPL-3.0-or-later — see LICENSE.