PHPackages                             jarir-ahmed/uncensored-search - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. jarir-ahmed/uncensored-search

ActiveLibrary[Search &amp; Filtering](/categories/search)

jarir-ahmed/uncensored-search
=============================

Framework-agnostic meta web-search client for PHP. Aggregates multiple search APIs (Tavily, Serper, Firecrawl, SearchApi, ScrapingBee, Scavio) with automatic failover and an unfiltered (safe-search off) mode.

v1.0.0(today)01↑2900%MITPHPPHP &gt;=7.4

Since Jun 10Pushed todayCompare

[ Source](https://github.com/jarir2020/jarir-ahmed-uncensored-search)[ Packagist](https://packagist.org/packages/jarir-ahmed/uncensored-search)[ RSS](/packages/jarir-ahmed-uncensored-search/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (1)Versions (2)Used By (0)

jarir-ahmed/uncensored-search
=============================

[](#jarir-ahmeduncensored-search)

A framework-agnostic **meta web-search client** for PHP. Point it at several search-API keys and it gives you one clean interface with **automatic failover**— if one provider is down, rate-limited, or returns nothing, the next one covers. Results are **unfiltered by default** (safe-search off); you opt back into filtering when you want it.

Supported providers: **Serper**, **Tavily**, **SearchApi.io**, **Scavio**, **Firecrawl**, **ScrapingBee**. All six have free tiers.

> This is *web* search (the open internet via search APIs). For searching your own indexed data (Elasticsearch, Meilisearch, …) see `jarir-ahmed/search`.

Install
-------

[](#install)

```
composer require jarir-ahmed/uncensored-search
```

Requires PHP 7.4+ and `ext-curl`.

Quick start
-----------

[](#quick-start)

```
use JarirAhmed\UncensoredSearch\UncensoredSearch;

// Load whatever keys you have — only configured providers are used.
$search = UncensoredSearch::fromKeys([
    'serper' => 'xxxx',
    'tavily' => 'tvly-xxxx',
    // 'searchapi' => '...', 'scavio' => '...', 'firecrawl' => '...', 'scrapingbee' => '...',
]);

$results = $search->search('open source vector database');

echo $results->provider();   // "serper" (whichever one answered)
foreach ($results as $hit) {
    echo $hit->title() . "\n";
    echo $hit->url() . "\n";
    echo $hit->snippet() . "\n\n";
}
```

### Loading keys

[](#loading-keys)

```
UncensoredSearch::fromKeys([...]);                 // inline array
UncensoredSearch::fromFile('uncensored_keys.txt'); // KEY=value / .env style file
UncensoredSearch::fromEnv();                        // SERPER_API_KEY, TAVILY_API_KEY, ...
```

Both naming styles are accepted in arrays and files: provider names (`serper`) or env-var names (`SERPER_API_KEY`).

Two search modes
----------------

[](#two-search-modes)

```
// FAILOVER (default) — try providers in order, first with results wins.
// Cheapest: one provider's quota per query.
$set = $search->search('php 8.4 release date');

// AGGREGATE — query every provider, merge, dedupe by URL. Max coverage,
// spends multiple quotas per call.
$set = $search->searchAll('php 8.4 release date');
echo implode('+', $set->providers()); // e.g. "serper+tavily+firecrawl"
```

The Query object
----------------

[](#the-query-object)

Safe-search is **off by default**. Everything is fluent and immutable.

```
use JarirAhmed\UncensoredSearch\Query;

$q = Query::create('climate data')
    ->withLimit(20)
    ->withSafeSearch(true)   // re-enable filtering (providers that support it)
    ->withCountry('us')
    ->withLanguage('en');

$search->search($q);
```

Working with results
--------------------

[](#working-with-results)

```
$set = $search->search('something');

$set->count();        // int  (ResultSet is Countable + iterable)
$set->isEmpty();      // bool
$set->first();        // ?Result
$set->provider();     // ?string — who served it
$set->providers();    // string[] — all contributors (aggregate mode)
$set->elapsedMs();    // float
$set->errors();       // array — why others were skipped
$set->toArray();      // array of plain rows

foreach ($set as $r) {
    $r->title(); $r->url(); $r->snippet();
    $r->source();   // provider name
    $r->position(); // ?int  rank
    $r->score();    // ?float (Tavily)
    $r->raw();      // untouched provider row
}
```

`search()` never throws on provider failure — failures land in `errors()` and an all-failed run simply returns an empty set you can inspect.

Choosing / ordering providers
-----------------------------

[](#choosing--ordering-providers)

```
// Restrict and reorder; tries tavily first, then serper.
$search->only(['tavily', 'serper'])->search('...');
```

Default failover order (best free quota / quality first): `serper → tavily → searchapi → scavio → firecrawl → scrapingbee`.

Command-line tool
-----------------

[](#command-line-tool)

```
php examples/cli.php "open source vector database"
php examples/cli.php --all --limit=5 "best php testing framework"
php examples/cli.php --safe "kids science fair ideas"
php examples/cli.php --keys=/path/to/keys.txt "php 8.4"
```

Provider reference
------------------

[](#provider-reference)

ProviderFree tierSafe-search switchNotesSerper2,500/moyesGoogle SERP JSON; default first choiceTavily1,000/monoAI-tuned snippets, relevance scoreSearchApifree creditsyesGoogle + many enginesScavio250/monoGoogle/Amazon/YouTube/RedditFirecrawl1,000/monoAI search; `data.web` resultsScrapingBee1,000/mopartialGoogle SERP; key in query stringGet keys from each provider's site, drop them in a `KEY=value` file, and **never commit it** — `.gitignore` already excludes `*.env` / `*keys.txt`.

Extending
---------

[](#extending)

Implement `Contracts\ProviderInterface` (or extend `Providers\AbstractProvider`for the shared mapping/decoding helpers) and pass your provider into the `UncensoredSearch` constructor. The failover engine and aggregator work against the interface, so no core changes are needed.

Testing
-------

[](#testing)

```
composer test
```

Tests use a fake HTTP client fed with **real captured provider JSON**, so no network or API quota is touched. 31 tests, 86 assertions, all green.

License
-------

[](#license)

MIT © Jarir Ahmed

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/20700f34ff813055154e843bbdbe04d33320c1e6a81bbb3301cad67cb8350fd3?d=identicon)[jarircse16](/maintainers/jarircse16)

---

Tags

searchSERPweb-search firecrawlaggregatorfailovertavilymeta-searchserperscrapingbeescavio

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jarir-ahmed-uncensored-search/health.svg)

```
[![Health](https://phpackages.com/badges/jarir-ahmed-uncensored-search/health.svg)](https://phpackages.com/packages/jarir-ahmed-uncensored-search)
```

###  Alternatives

[elasticsearch/elasticsearch

PHP Client for Elasticsearch

5.3k184.2M1.0k](/packages/elasticsearch-elasticsearch)[ruflin/elastica

Elasticsearch Client

2.3k51.7M218](/packages/ruflin-elastica)[solarium/solarium

PHP Solr client

93433.9M111](/packages/solarium-solarium)[opensearch-project/opensearch-php

PHP Client for OpenSearch

15227.1M101](/packages/opensearch-project-opensearch-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
