Metadata-Version: 2.4
Name: findable
Version: 0.1.2
Summary: Score how findable a website is, from the outside. No account, no key, no dependencies.
Author-email: Guestar <admin@guestar.ai>
License: MIT
Project-URL: Homepage, https://guestar.ai/get-found
Project-URL: Source, https://github.com/guestarAI/findable
Keywords: seo,audit,website,discoverability,cli,ai-search
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# findable

Score how findable a website is, from the outside. No account, no API key, no signup.

```
$ pipx install findable
$ findable example.com
```

Prefer not to install anything? The hosted version at
[guestar.ai/get-found](https://guestar.ai/get-found) runs the same engine and adds a written
explanation of what to fix first.

![findable running against guestar.ai](https://raw.githubusercontent.com/guestarAI/findable/main/demo.gif)

*Run against our own site, because a checker whose author exempts himself is not worth much.*

## Why another site checker

Most of them are lead-capture forms that email you a PDF of colour-coded acronyms. This is a
CLI that prints findings a business owner can act on, and a library you can build on.

Three things it does differently:

**It writes for the owner, not the developer.** No "schema", no "canonical", no "SERP". There
is a [unit test](tests/test_findable.py) that fails the build if a finding contains jargon.
"Search engines cannot tell what kind of business you are" is a thing someone can act on;
"missing LocalBusiness schema" is a thing they have to go and look up first.

**A check it could not run never costs you points.** Unknowns shrink the denominator instead
of the score. If bot protection blocks the sitemap probe, you do not get marked down for a
sitemap we never looked at. Tools that penalise unknowns are really scoring how hard your site
is to crawl, and telling you it is a quality problem.

**It checks whether you come up for your own name.** Optional, because it needs a search
provider, and skipped rather than guessed at when there isn't one. It is usually the most
useful line in the output: plenty of businesses have a perfectly good website that does not
appear when someone searches the name on their own business card.

## Install

No dependencies, so any of these work:

```
pipx install findable    # isolated, recommended
pip install findable
git clone https://github.com/guestarAI/findable && cd findable && python3 -m findable example.com
```

## Use

```
findable example.com                 # human-readable
findable example.com --json          # machine-readable
findable example.com --search        # also check your own name in search
```

`--search` needs a provider key in the environment:

```
export JINA_API_KEY=...      # or BRAVE_API_KEY
findable example.com --search
```

Exit code is `1` when a high-severity finding exists, so it works in CI:

```yaml
- run: pip install findable && findable "$SITE"
```

As a library:

```python
from findable import check
from findable import providers

report = check("example.com", search=providers.auto())
print(report.score, report.grade)
for f in report.findings:
    print(f.severity, f.title, "->", f.fix)
```

Bring your own search provider, it is just a callable:

```python
report = check("example.com", search=lambda q: my_search(q))   # -> list[str] of URLs
```

## What it checks

| | |
|---|---|
| **Can search engines tell what you are?** | page title, summary, machine-readable business description, main heading, share preview image |
| **Can they find all of your pages?** | robots, sitemap, `llms.txt`, mobile rendering |
| **Can a customer actually reach you?** | enquiry form, email / phone / WhatsApp links, one-tap contact |
| **Does the site look looked-after?** | most recent date, regularly published content, linked social profiles, how much there is to read |
| **Do you own your own name?** | optional, needs a search provider |

It also detects a site that is **suspended or parked** — returning valid HTML and HTTP 200
while serving nothing. That case is invisible to signal-level checks and it is usually the
most urgent thing you can tell someone.

## If you build on this

The SSRF guard in `fetch.py` is not decoration. If you expose this over HTTP, a service that
fetches a user-supplied URL from inside your network can be pointed at `127.0.0.1` or at
`169.254.169.254` for cloud metadata. The guard resolves the hostname before judging it, and
re-runs on **every redirect hop** — checking only the first is a real bug with a real exploit.

A warning that cost us time: **do not scrape a search engine from your own IP and trust the
result.** Bing returned us a page with the correct title, our query echoed back, and ten
well-formed result rows whose URLs decoded cleanly to a children's clothing retailer on one
run and French anime sites on the next. It looks exactly like a working provider. If you add
a scraper, assert that results contain the query's own terms before trusting any of them.

## Limits

Reads one page plus two small probes. It cannot see your traffic, your rankings, or anything
behind a login, and it does not pretend to. It tells you where it could not look.

## Licence

MIT. Built by [Guestar](https://guestar.ai), which runs a hosted version at
[guestar.ai/get-found](https://guestar.ai/get-found) that adds an AI-written explanation of
what the findings mean for your particular business.
