I've been working on a generator of synthetic URLs for training and testing phishing detectors, and I've released it with its full evaluation: https://github.com/youssefismail-dev/limnex-uie (Apache-2.0, code and weights).
The motivation is a data problem. Phishing URLs are scarce, feeds only contain what was caught and reported, a URL is usually dead within days, and the data is awkward to share. Limnex UIE is a 25.5M-parameter character-level transformer, trained from scratch on Common Crawl URLs and the OpenPhish community feed. It doesn't use a pretrained model, word lists or templates. The final model is small enough that training it takes only about 3.5 hours on a free Kaggle T4, so anyone can retrain it. Getting there took a few months and dozens of pre-registered experiments.
I think the evaluation is the more interesting part, so most of this post is about that.
Realism is graded one URL field at a time. For each field (label, suffix, subdomains, path, query) and each class, a classifier tries to separate generated strings from held-out real ones. Two real samples don't score an AUC of 0.5 against each other, so the score is the excess AUC over a real-vs-real floor, measured over 5 independent generations, and a cell passes only if that excess is shown to be below 0.05. 29 of 32 cells pass. The ones that don't are written up in detail: phishing query strings in free mode are still detectable, and so is the vocabulary. A detector that simply checks whether each word appears in real data separates whole URLs quite easily (an excess of about +0.16), even though character-level detectors don't. In a small human test, ten people got 55 of 100 right, which says little either way.
I also compared it with simpler generators trained on the same rows and passed through the same filter: a 5-gram model, a 2x512 char-LSTM, Qwen2.5-7B-Instruct prompted with 20 real examples per request, and rule-based look-alike domains (typos and character swaps, in the style of the dnstwist tool). UIE was more realistic in 28 of 31 comparisons, with 3 ties and none where a baseline came out ahead. The LLM was the least realistic of the learned generators: its URLs look tidy to a person, but they're stereotyped, with few suffixes and almost no query strings. One caveat is that UIE was developed against this test. A word-level detector built after the model was frozen gives the same ranking, which helps, but it isn't a complete answer.
The question I cared about most was whether the data actually helps detectors, so I pre-registered it. A char CNN and a hashed n-gram logistic regression were trained on 1k, 10k and 100k real URLs per class, with and without synthetic URLs, and tested once on phishing that appeared after UIE's training data ended. Adding UIE's URLs helped in all 6 settings, by 2.7 to 24 points of recall at 1% FPR, most when real data was scarce. Helping more than the best simpler generator held in only 1 of 6, though. UIE was ahead in 5 of 6, but by small margins, and on PhreshPhish the LLM's URLs helped more in 4 of 6 despite being the least realistic. So realism and usefulness turned out to be different things, which I didn't expect going in.
As a case study, I retrained two members of my own phishing detector (about 1M real training URLs) with UIE's data, and recall at 1% FPR on its frozen external test went from 0.272 to 0.544 (95% CI +0.15 to +0.41). That number needs its caveats: it's one benchmark and one seed, a large part of the gain comes from one phishing family (look-alike pages on Blogger's country domains), and the retrained models got slightly worse on the detector's older validation data.
On safety: it only writes URL strings, with no pages, lures or DNS lookups. Every generation has to pass a Bloom filter of the 14.9M training-side URLs, which removes copies of real URLs (about 1 in 100 raw phishing samples is one), and no bulk generated phishing is published.
It's a v0.1.0 research release with real limits: one phishing source, URLs from 2024 to 2026, and about 2 URLs per second on a laptop CPU. I built it with Claude Code as a coding assistant, which is credited in the README. Criticism of the evaluation is the feedback I'd value most.