Transparency Report

Service usage · Abuse handling · Legal interactions

Last updated: June 2026 · Author: Sean Wei

tg.pe is a small, free URL shortener run by one person. This is an honest look at what it does behind every link, and how it handles the people who try to weaponise it for phishing and scams.

If you are a security researcher, network operator, or internet-governance reader, the numbers, methodology, and full change history are in For researchers below.

A stranger reported a scam

A German-language parcel-delivery phishing mail reached Stefano with a “Pay now” button on a tg.pe link. He forwarded it to abuse@tg.pe: “this looks like a SPAM Mail and abuse of your service.” 50 minutes later the link was a 404, the account banned, the destination block-listed. His reply: “Awesome, didn't expect a reply.” The default experience of reporting abuse online is a black hole; what makes the difference here is not budget, it is that someone is paying attention.

The numbers

Service usage

Short links created (lifetime)31,674
Removed for safety / abuse2,152 (6.8%)
Active links currently served29,522
Total clicks served (since April 2026)94,410
Service age6 years 8 months

Abuse handling

External abuse reports received (lifetime, from CERTs / vendors / individuals)313
Median time from external report to removal~4 hours
Submitters currently banned206

Legal interactions

Law-enforcement requests, court orders, DMCA / UDRP / URS notifications, and acquisition / policy-change inquiries received in 6+ years: 0 across the board. Full position in Who runs it & your data.

How links stay safe

Every link is checked before it goes live, checked again in the background moments later, and then re-checked when it is clicked, at most once a week per link, not on every click. None of these checks is perfect; each catches what the others miss. The slow ones run after the response is flushed, so nobody waits while they finish.

tg.pe runs no ads and sells no data; it redirects to the exact URL submitted and strips platform trackers (fbclid, gclid, igshid) first.

Who runs it & your data

For researchers

Everything above is the short version. What follows is the depth: the measurement and data first, then the engineering of the safety pipeline, then the ecosystem and outcomes, written for security researchers, network operators, and internet-governance readers, with the methodology and the open questions kept honest throughout.

Measurement & data: domain age and RDAP coverage

For every destination, tg.pe resolves the age of the registrable parent domain and records which source answered. RDAP is tried first; when RDAP is silent (typically a ccTLD outside the IANA bootstrap), CIRCL Passive DNS first-seen serves as a second tier; and a VirusTotal WHOIS-derived creation date is a further fallback in the background pass. The synchronous resolver (resolveDomainAge()) tags its answer as rdap or pdns; the background VirusTotal pass records its own source=virustotal in malicious_detections separately.

That source tag is the interesting part. It turns a routine safety check into a small, live, reproducible instrument for a real DNS-abuse-governance question: where is RDAP actually answering, and where does the ecosystem still fall back to weaker signals? The sections below report what the instrument has shown so far. All of it is preliminary and open: a curiosity this tooling could be extended into a study, not a settled result.

The two-population domain-age picture

Observed in practice, on a small sample: the destinations split into two populations. Freshly-registered throwaway domains are caught early, at submission, by the new-domain and smartlink honeypots; they never reach a human. The destinations that instead reach an operator takedown after an external report tend to be compromised, established sites, where the registration date says nothing useful about intent. This is an observation, not a rate: the usable sample is small, partly because legacy removals scrubbed the destination before the registration date was retained (see the gaps list). Treat it as a shape worth probing, not a finding.

RDAP bootstrap coverage (preliminary)

RDAP coverage observed in practice is uneven. gTLDs are essentially complete in the IANA RDAP bootstrap; ccTLD coverage is patchy. The Peru .pe ccTLD (tg.pe's own TLD) is absent from the bootstrap, which is precisely why CIRCL Passive DNS first-seen is needed as a second tier at all. And bootstrap presence understates real deployment: several registries run RDAP servers that are not listed in the bootstrap (unlisted or "stealth" servers), so a TLD can be answering RDAP while reading as uncovered.

Three method disclosures are needed before any coverage figure from this tooling is cited, because each one biases what "covered" means here:

The reproducible figure to publish is the RDAP-hit vs pDNS-fallback vs VT-fallback rate, broken out by gTLD vs ccTLD, ideally a small per-TLD table, each row pinned to a snapshot date, an observation window, and a denominator. Until that query is run against the live source tag, no ccTLD-coverage number is stated here.

The open direction this points at: a per-ccTLD study joining stealth-inclusive RDAP deployment (probing for unlisted servers, not just reading the bootstrap) with response conformance (does the server actually return a usable registration event?). tg.pe's source-tagged data is one small, real-world input to that, no more.

Methodology & definitions

This report is generated from a snapshot of the production MySQL database plus the operator's mail archive.

The safety pipeline: architecture & rationale

tg.pe layers its checks at three points: before a link goes live, after the response has been flushed to the client, and again on every later click. The split is deliberate. The synchronous checks are the ones cheap enough to add to the user-visible latency budget; everything slow runs strictly after the response is flushed, so it adds safety without adding latency anyone feels. The stage table below makes the blocking/non-blocking boundary explicit, and the design notes explain the non-obvious choices. This is the part most directly reusable by another small operator; the contact section means that invitation seriously.

Stage-by-stage

Grouped by where each stage runs. The Blocking? column marks which checks are strictly pre-response (they add latency the submitter waits on) versus strictly post-flush (no user-visible latency). Fail-mode is what happens when the external dependency is unavailable.

Stage Data source Blocking? On hit Fail-mode Logged to
Before the link goes live (synchronous, adds latency)
Domain blacklist & high-risk list Local curated lists Blocking Blacklist (47): refuse on both channels. High-risk (353): refuse on Web only; identified Telegram users pass. n/a (local) submission_rejects
Newly-registered-domain check RDAP (via rdap.org); CIRCL pDNS second tier Blocking Web < 30 days / Telegram < 7 days → one-hour honeypot, operator notified. ccTLD with no RDAP falls to pDNS first-seen. Fail-open (null age is never treated as "new") submission_rejects
Ad-smartlink pattern Local pattern match Blocking CPM/affiliate smartlink shape (ad-network hosts, opaque key params, unfilled affiliate macros) → one-hour honeypot, flagged. n/a (local) submission_rejects
Google Safe Browsing: at submission Google Safe Browsing API Blocking Threat-category match → refuse before the short link is created. Fail-open: API error lets it through, logged error log + submission_rejects
Submitter rate limit Local counters Blocking Two-layer: Web 5/hr (anon non-TW) up to 20/hr (identified) plus a 10-minute burst cap; Telegram 60/hr plus a 20-per-10-min burst cap → refuse. The burst layer is what stops the cron-bot spikes. n/a (local) rate_limit_hits
After the response is flushed (background, no user-visible latency)
VirusTotal reputation + creation date VirusTotal v3 /domains Post-flush Malicious verdict (≥ VT_MALICIOUS_MIN = 2 engines) or brand-new on an RDAP-missed TLD → tighten link to 30-min expiry. Whitelist: telegra.ph, graph.org, t.me (Telegram-owned, abused on sub-paths only) are never flagged. Fail-open (any VT failure / rate-limit leaves the link untouched) malicious_detections
urlscan.io capture urlscan.io Post-flush New-domain / VT honeypots get a screenshot, redirect chain, contacted hosts. Runs on urlscan's infrastructure → hostile page never fetched from tg.pe's server. Becomes evidence for onward reports. Fail-open (no capture, no penalty) capture stored with the link
Submitter IP screen AbuseIPDB Post-flush New non-Taiwan Web submissions scored; AbuseIPDB confidence score > 75 → link expired within a second or two of creation. Never runs for Telegram. Fail-open error log
Google Safe Browsing: re-check on later clicks Google Safe Browsing API Post-flush (after redirect sent) Only if last check > 7 days; atomic claim so concurrent clicks check once; flagged → removed, operator notified. Fail-open: next click re-checks error log
Always on
Manual abuse intake abuse@tg.pe and /abuse n/a Triaged by hand; the verified median from external report to removal is ~4 hours (one stranger-reported case closed in 50 minutes). n/a mail archive
Machine-readable security contact security.txt (RFC 9116); OpenPGP via WKD n/a Kept current; enables encrypted reports. n/a n/a

Design notes: why it works this way

Why it works this way (design rationale)
  • Honeypot, not hard refusal. A brand-new-domain or smartlink submission is created with a one-hour expiry rather than refused; the submitter sees success while the operator is notified at once. A hard refusal would hand the adversary a clean feedback signal ("this destination is flagged, rotate it") which the honeypot deliberately denies.
  • urlscan.io scopes the SSRF claim precisely. The capture runs on urlscan's own infrastructure, so a hostile page is never fetched from tg.pe's server. This is not a claim that tg.pe never contacts destinations. RDAP and VirusTotal lookups are made by tg.pe directly; the precise claim is only that the page-rendering fetch of a flagged hostile destination is offloaded.
  • Fail-open Safe Browsing is an honest tradeoff and an admitted attack surface. A GSB API error lets the submission through and is logged, rather than blocking legitimate users on Google's downtime. The honest counterpoint: a GSB outage is a window, and it is named as a known limitation. The mitigation is that it is logged and the next click triggers a fresh check, not that the window doesn't exist.
  • The click-driven re-check is atomically claimed. Re-scanning ~30,000 idle URLs daily would burn API quota for nothing; the re-check instead fires the moment someone is about to be exposed, and only if the last check is > 7 days old. To stay safe under concurrency, the work is claimed atomically before it runs, so a burst of concurrent clicks on the same stale link triggers exactly one re-check, not one per click.
  • The ordering/latency contract. Synchronous stages complete before the redirect is emitted; the connection is then flushed and closed, and only after that do VirusTotal, urlscan.io, the AbuseIPDB screen, and the GSB re-check run. A link a background check flags is expired seconds later, live too briefly to circulate, but the submitter never waited on the check.
  • Asymmetric trust. Web is anonymous and mutable, so it gets the stricter thresholds (30-day new-domain window, tighter rate limits, no custom codes, the AbuseIPDB screen). Telegram identity is durable and bannable, so it is trusted further (7-day window, higher rate limit, high-risk list bypassed); one ban then clears that user's whole history.

What the automation catches

The logging is built to measure the defence funnel, not just to fire alerts. EventLog::logReject() writes one row per failing stage into submission_rejects, by design, so the operator can measure how much each stage caught on its own versus in overlap across blacklist / new_domain / safe_browsing / abuseipdb; and malicious_detections records the source, reason, and engine counts for each background tightening. The data to publish a per-stage funnel (how many submissions each stage caught, how much each stage caught uniquely, and the marginal value of each external dependency) already exists; at this n it must be clearly labelled as small.

One slice is reportable now. Of the background VirusTotal scans run since that pass went live, 49 tightened a just-created link to a 30-minute expiry with no operator in the loop, split below. The denominator (49 of how many total background scans) is what turns this from an anecdote into a measurement, and that count belongs in the funnel table above.

Malicious reputation verdict42
Brand-new domain on an RDAP-missed TLD7

Shown honestly, this is also where the layers overlap: some of these 43 would have been caught by another stage too. The funnel table is the place to show which stages are redundant and which are load-bearing, rather than implying every layer is independently essential.

Removal & response

Removal authority comes from the public Terms every submitter accepts: phishing, malware, scams, CSAM, harassment. One Telegram ban soft-deletes every link that user ever created. Re-check is click-driven: a click on a link not checked in the last 7 days triggers a fresh Safe Browsing call. The verified figure is a ~4-hour median from external report to removal; that median describes active response, not all removals, because backlog cleanup and ban-cascade sweeps are much older and would otherwise pull it out of shape. The tables below are the integrator's database output.

Removal timing & re-check volume (tables)

Time from creation to removal

How old each link was when it came down. The top group is active response to fresh abuse; the bottom group is backlog cleanup and ban-cascade sweeps, whose timings reflect when the operator audited, not when the abuse was first detected.

URL age at removalRemovals%
Active response
Under 1 hour627.3%
1 – 24 hours22026.0%
1 – 7 days20123.8%
Backlog cleanup & ban cascade
7 days – 1 year29735.1%
Over 1 year657.7%

Excludes 1,296 links soft-deleted in a single batch on 2025-01-06 21:24, a one-time inventory cleanup whose synthetic timestamps would distort the distribution.

Re-check coverage

Live Google Safe Browsing calls fired against existing short links since the April 2026 integration:

WindowLive re-checks
Last 7 days679
Last 30 days2,644
All-time (since integration)3,104

The other ~25,000 active links pre-date the Safe Browsing integration; their last_safety_check_at was backfilled to creation date at the April 2026 migration. Their first live check fires on the next click. Most never get one (see the long tail under Click distribution), which is by design: idle URLs shouldn't burn API quota until somebody is about to be exposed.

Abuse reports & real cases

External reports come from national CERTs, anti-fraud vendors, and ordinary recipients. Over the service's life the top three sources (CIRCL, the US IRS, and Netcraft) are ~76% of volume; the long tail confirms tg.pe sits on multiple watchlists.

The candid part is the misses, and what each one changed. The worst category (July 2022): a Tor-routed report flagged a tg.pe link as the entry point to a child-sexual-abuse archive; the operator confirmed and removed it within 8 hours. It is the only non-phishing abuse case in 5+ years, and the reason takedown, block list, and bans apply equally to the worst categories, not just phishing. 2022 IRS campaign: IRS auto-detection forwarded 73 reports and CIRCL added 108 (~199 in two quarters, more than every other quarter combined); ASN-level banning was rolled out in response. European bank clones (2021–2023): Société Générale, Crédit Agricole, La Poste, Deutsche Postbank, Alpha Bank, ČSOB, each reported by a different organisation, each removed within hours. Orange France (April 2021): a two-week run of 15+ links to cloned Orange login pages; the operator removed each and hand-banned the submitter IPs, part of why IP/ASN blocking became core.

Reporters & yearly volume (chart & table)

Yearly volume and response time

Reports = external incoming. Links reported = distinct tg.pe/{code} short links named in those reports. Response time = median time from first report to removal.

Year Reports Links reported Response time Notes
2026 (YTD)422.4 hIncludes the parcel-delivery scam reported by an ordinary user (the featured case above).
20251834.6 hQ4 spike (mail-server-side incident, not tg.pe-shortened content); same-day handling.
2024835.2 hMostly Netcraft; same-day handling.
20233972.9 hVolume dropped; remaining reports handled within hours.
2022207265.1 hIRS impersonation + CIRCL bulk wave, the largest sustained external pressure to date.
202125372.5 hFirst-line defences built (see timeline). Many reports came as multi-code batches.
20201224.8 hFirst reports arrived (Cloudflare / Netcraft / DigitalOcean). Tiny volume.

The 2022 row is the most meaningful: even at peak external pressure, median report-to-removal held ~5.1 hours.

Reporting abuse onward

Removing a link from tg.pe does not remove the threat from the internet. When the operator confirms a removed destination is malicious and classifies it, the indicator is reported onward to the abuse-handling community (feeds, vendors, and registrars) so the underlying page can be acted on wherever else it is reaching people. Each report goes only to the channels that fit it; a mis-routed report burns reporter reputation, which is the scarce resource here.

The volume is small and deliberate. Counting only successful sends: 13 outbound reports, 3 distinct destinations, 7 channels reached, 3 via API and 10 assisted-manual. The seven channels are CIRCL MISP, abuse.ch ThreatFox, Netcraft, the DNS Abuse Institute's NetBeacon, Google Safe Browsing, Microsoft SmartScreen, and phish.report. MISP events carry machine-readable taxonomy tags: TLP:GREEN, source:tg.pe, an incident classification, and the destination's registration age, the same registration-age datum the new-domain check resolves (the measurement section). CSAM is never sent to these phishing/malware feeds; it is referred out of band to NCMEC, the IWF, or law enforcement.

Per-channel breakdown (where the 13 went)
ChannelMethodReports
Netcraftmanual3
Google Safe Browsingmanual2
Microsoft SmartScreenmanual2
NetBeaconmanual2
phish.reportAPI + manual2
abuse.ch ThreatFoxAPI1
CIRCL MISPAPI1

All were phishing or scam; no malware or CSAM has been routed to these feeds.

A report that closed the loop (and one that didn't)

One case is documented end to end. On 25 May 2026 a tg.pe link to a Flipkart-impersonation phishing page on gauseva.life was removed and reported to five channels. On 2 June 2026 phish.report confirmed the domain suspended by its registrar (case case_fn4ae2bso6ps), eight days from removal to suspension, with an external reference the operator did not generate. The honest counterpoint from the same period: a cloaked affiliate smartlink reported to Netcraft came back "no threats found"; monetisation redirectors serve benign content to datacentre scanners, so not every report closes. This is n=1 closed and n=1 not. It is not evidence that reports lead to takedowns, and nothing here should be read as "typically" or "usually". What fraction of onward reports end in a confirmed removal is not yet measured (see the gaps list).

Bans & domain lists

206 submitters are currently banned, all Telegram users; a ban soft-deletes every link that user ever created. No Web submitter has ever been individually banned; Web abuse is stopped upstream by the safety pipeline, and Web IPs are too mutable to ban usefully. The verified central figure is a median of 2 links before a ban; the higher percentiles are integrator database output, below.

Domain lists

ListCountExamplesBehaviour
Block list47Phishing landing pages, malware distribution sitesRefused on both Web and Telegram.
High-risk list353Other URL shorteners, free hosting platformsRefused on Web only; identified Telegram users pass.
Links-before-ban distribution (206 banned accounts)
Median (50th percentile)2
75th percentile3
95th percentile11

Safety-mechanism timeline

The change history, paired where relevant with the miss each fix responded to.

What's not in this report (yet)

Contact

Abuse, or anything in this report: abuse@tg.pe

If anything here is useful (for research, for policy work, or if you run a similar service and want to compare notes), please reach out. tg.pe is a small operation, but small operators are part of how URL-level abuse gets contained, and the operator would rather share than keep it private.