LinkShieldAI Python SDK
Python wrapper for the LinkShieldAI API at https://api.linkshieldai.com.
The SDK supports:
- URL risk scanning with
POST /v1/scan - Three scan depths:
standard,detailed,deep - Optional model analysis and raw signal output
- Screenshot download
- NSFW site checks
- Chimera AI classification
- Sync and async clients
- Retry/backoff for transient API failures
- A small command-line tool
Install
pip install linkshieldai
Authentication
The API uses Bearer authentication. The key is sent in the Authorization
header and never in the query string.
from linkshieldai import LinkShieldAI
client = LinkShieldAI(api_key="YOUR_API_KEY")
Or set an environment variable:
$env:LINKSHIELDAI_API_KEY = "YOUR_API_KEY"
from linkshieldai import LinkShieldAI
client = LinkShieldAI()
Scan a URL
Wraps:
POST https://api.linkshieldai.com/v1/scan
from linkshieldai import LinkShieldAI
with LinkShieldAI(api_key="YOUR_API_KEY") as client:
result = client.scan("https://example.com", mode="standard")
print(result.verdict) # SAFE, MALICIOUS or UNKNOWN
print(result.request_id)
print(result.reason_codes)
if result.is_malicious:
print("Block or review this URL")
Verdicts
verdict is SAFE, MALICIOUS or UNKNOWN.
UNKNOWN means no decisive signal was available. It does not mean safe, and
is_safe is False for it:
| verdict | is_malicious |
is_safe |
is_unknown |
|---|---|---|---|
MALICIOUS |
True |
False |
False |
SAFE |
False |
True |
False |
UNKNOWN |
False |
False |
True |
Modes
| mode | What it adds |
|---|---|
standard |
Fast reputation and threat-feed decision. |
detailed |
Redirect, page-preview, brand, and screenshot signals when available. |
deep |
Page fingerprinting when earlier signals are inconclusive. |
Model analysis
Pass ai=True to add model analysis when page fingerprinting is inconclusive.
It is off by default and applies to deep only, since the model scores the page
HTML that only deep fetches. Without it, risk_score and confidence stay
None.
result = client.scan("https://example.com", mode="deep", ai=True)
print(result.verdict, result.risk_score, result.confidence)
Raw signals
reason_codes tells you why a verdict was reached. include_signals=True also
returns what each source independently reported, so you can apply your own
precedence:
result = client.scan("https://example.com", include_signals=True)
if result.signals:
print(result.signals.url_reputation) # malicious | safe | unknown
print(result.signals.domain_reputation)
print(result.signals.threat_feed)
print(result.signals.external_reputation) # bool
print(result.signals.degraded) # a lookup failed
Result fields
result.verdict # SAFE | MALICIOUS | UNKNOWN
result.request_id # quote this in support tickets
result.mode
result.confidence # None unless ai=True
result.risk_score # None unless ai=True
result.threat_categories
result.reason_codes
result.brand_target # detected impersonation target, if any
result.screenshot_url
result.submitted_url
result.normalized_url
result.redirects
result.scanned_at
result.freshness
result.engine_version
result.signals # None unless include_signals=True
result.raw # the untouched JSON payload
Async
import asyncio
from linkshieldai import AsyncLinkShieldAI
async def main():
async with AsyncLinkShieldAI(api_key="YOUR_API_KEY") as client:
result = await client.scan("https://example.com", mode="deep", ai=True)
print(result.verdict)
asyncio.run(main())
Other endpoints
nsfw = client.nsfw_check("https://example.com")
print(nsfw.is_nsfw)
chimera = client.chimera("https://google.com")
print(chimera.result, chimera.probability)
image_bytes = client.get_screenshot("05046f.png")
client.get_screenshot("https://api.linkshieldai.com/screenshot/05046f.png", "site.png")
Command line
linkshieldai --api-key YOUR_API_KEY scan https://example.com
linkshieldai --api-key YOUR_API_KEY scan https://example.com --mode detailed
linkshieldai --api-key YOUR_API_KEY scan https://example.com --mode deep --ai
linkshieldai --api-key YOUR_API_KEY scan https://example.com --include-signals
linkshieldai --api-key YOUR_API_KEY nsfw https://example.com
linkshieldai --api-key YOUR_API_KEY chimera https://google.com
linkshieldai --api-key YOUR_API_KEY screenshot 05046f.png --output site.png
Omit --api-key when LINKSHIELDAI_API_KEY is set.
Custom API host
client = LinkShieldAI(api_key="YOUR_API_KEY", base_url="https://api.linkshieldai.com")
Timeouts and retries
Defaults are timeout=10.0, max_retries=2, backoff_factor=0.5.
Retries apply to temporary connection failures and HTTP 429, 502, 503 and
504. Retry-After is honoured when the API sends it.
client = LinkShieldAI(api_key="YOUR_API_KEY", timeout=15.0, max_retries=3)
Errors
from linkshieldai import (
APIConnectionError,
APIResponseError,
APIStatusError,
AuthenticationError,
RateLimitError,
)
| Error | Raised when |
|---|---|
AuthenticationError |
No API key was provided. |
RateLimitError |
HTTP 429. Carries retry_after when the API sends it. |
APIStatusError |
Any other non-success status. Carries status_code. |
APIResponseError |
Malformed JSON, or a payload containing an error. |
APIConnectionError |
Timeouts, DNS failures, connection failures. |
Upgrading from 0.2.x / 0.3.0
basic_check() and detailed_check() have been removed. Use scan():
# before
result = client.basic_check(url)
if result.is_malicious: ...
# after
result = client.scan(url)
if result.is_malicious: ...
# before
result = client.detailed_check(url)
print(result.screenshot_url, result.tag)
# after
result = client.scan(url, mode="detailed")
print(result.screenshot_url, result.brand_target)
The CLI commands basic and detailed are replaced by scan --mode.
The underlying GET / and GET /classify_link endpoints still work and are not
being removed without notice, so existing direct HTTP integrations are
unaffected.
Documentation
Metadata
Release files for linkshieldai 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| linkshieldai-0.3.1.tar.gz | 13.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| linkshieldai-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.3 kB
Release files / linkshieldai-0.3.1.tar.gz
| Download URL | linkshieldai-0.3.1.tar.gz |
|---|---|
| Size | 13.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cb3e6d4e85172675cb71502b07cca790bb00dd36b26a724f5859d54d2bbfbfaf
|
|
BLAKE2b-256 checksum How to use checksums |
c5861c9ca7bb5dd4940621e3f98ce4110f15878b34adbfa61c4fb79232c099eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.10
|
Release files / linkshieldai-0.3.1-py3-none-any.whl
| Download URL | linkshieldai-0.3.1-py3-none-any.whl |
|---|---|
| Size | 14.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e858847c005e25885fa0ca58a063a3e9c41651f76ea7cd121e870876f0911b50
|
|
BLAKE2b-256 checksum How to use checksums |
aede88d0bde6c66f2ad6c18da2c0efd4eb21a3db8a6e77e373c1c974d5dc825e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.10
|