Multi-Modal Fraud & Quality Detection with Vision LLMs

For curators, product discovery, and listing validation platforms: detecting fake products, scams, and inflated claims is a precision game. A false reject (wrongly blocking a legitimate EU product) damages a seller and erodes curator trust. A false negative (a phishing site or fraudulent listing shipping) damages users and violates platform integrity. This guide shows how to balance both using multi-modal analysis — screenshot + text signals + claims — with Qwen3 Vision LLMs and structured JSON verdicts.

Start building: Get a free JuiceFactory API key — no credit card required.

The Threat Model

Curation workflows process hundreds of product submissions. Adversaries exploit this scale:

  • Fake product sites: Parked domains, login walls with no content, error pages, placeholder copy — noise that pollutes a high-trust directory.
  • Phishing & brand impersonation: A page masquerading as Slack or Notion, asking users to "log in" to a malicious auth endpoint.
  • Inflated claims: A tool claims "EU data residency" and "GDPR-native," but the privacy policy is missing or states data flows to US cloud providers. Claims and reality diverge.
  • Scam/deception: Crypto yield schemes, "get rich quick" overlays, fake testimonials, or obfuscated payment models.
  • Bot pages & detritus: Automatically generated content farms, promotional spam, or machine-translated garbage.

The defender's dilemma: catching fakes requires skepticism, but excessive skepticism (high false-positive rate) blocks real products and kills curator velocity.

The Detection Architecture: Screenshot + Text + Claims

Multi-modal fraud detection combines three signal streams into a single, structured verdict:

  1. Screenshot (visual): What the page looks like — layout, branding, UI cues, visual artifacts of automation.
  2. Text signals (structured metadata): Page title, meta description, headings, body text, presence of privacy policy & company imprint.
  3. Submitter claims (ground truth to verify): What the product claims to be — name, category, pricing model, data location, sovereignty assertions.

The model fuses these three into a binary or ternary decision:

  • pass: Legitimate product, claims match reality, no red flags.
  • review: Uncertain; claims don't align perfectly with page, or missing evidence for sovereignty claims. Escalate to human curation.
  • reject: Fraud, phishing, scam, or irrelevant page. Block listing.

Real Implementation: LaunchRadar + Qwen3-VL

Here's how it works in practice (from LaunchRadar, a curated directory of sovereign, GDPR-native EU software):

System Prompt (Trust & Safety Frame)

You are a trust & safety and product reviewer for LaunchRadar, a curated directory 
of sovereign, GDPR-native European software. You are given a SCREENSHOT of a submitted 
product's homepage, extracted page TEXT/signals, and the submitter's CLAIMED listing fields.

Assess strictly and skeptically:
1. Is this a REAL, legitimate software product — not a scam, phishing page, 
   crypto/"you won" scheme, brand impersonation, malware/deceptive page, 
   login wall with no info, or a parked/empty/error page?
2. Do the submitter's claims (name, what it does, category, pricing) match 
   what the site actually shows?
3. Are the sovereignty claims plausibly supported? gdprEvidence/euOwnedEvidence 
   = is there a privacy policy, imprint/impressum, EU company info, or 
   European language/market signals backing GDPR-native / EU-owned / 
   EU data residency?

Notice the framing: strict and skeptical, naming the specific threats (scam, phishing, brand impersonation, parked pages), and requiring evidence for claims, not assertions.

Input Schema

export type Claims = {
  name: string;
  url: string;
  tagline?: string | null;
  description?: string | null;
  category?: string | null;
  pricing?: string | null;
  dataLocation?: string | null;
  gdprNative?: boolean;
  euOwned?: boolean;
  selfHostable?: boolean;
  openSource?: boolean;
};

const signals = {
  finalUrl: scrape.finalUrl,
  blocked: scrape.blocked,
  title: scrape.title,
  metaDescription: scrape.metaDescription,
  ogDescription: scrape.ogDescription,
  headings: scrape.headings,
  hasPrivacyPolicy: scrape.hasPrivacyPolicy,
  hasImprint: scrape.hasImprint,
  bodyText: scrape.bodyText,
};

The submitter provides claims (what they say their product is). The scraper provides signals (what the page actually contains). The vision LLM's job is to spot mismatches and verify sovereignty assertions.

The API Call

const res = await fetch(`${api()}/v1/chat/completions`, {
  method: "POST",
  headers: { 
    "content-type": "application/json", 
    authorization: `Bearer ${KEY}` 
  },
  body: JSON.stringify({
    model: "qwen3-vl",                    // Qwen 3 Vision LLM
    temperature: 0.2,                     // Low temp for deterministic, precise output
    max_tokens: 1600,
    response_format: { type: "json_object" },  // Force JSON-mode (no prose)
    messages: [
      { role: "system", content: SYSTEM },
      { role: "user", content: [
        { type: "text", text: `SUBMITTER CLAIMS:\n${JSON.stringify(claims)}\n\nPAGE SIGNALS:\n${JSON.stringify(signals)}\n\nReview the screenshot and the above...` },
        { type: "image_url", image_url: { url: `data:image/jpeg;base64,${screenshotBase64}` } }
      ]}
    ],
  }),
});

Key tuning decisions:

  • Temperature 0.2: General research on LLM phishing detectors tends to report better precision at lower temperatures (~0.2–0.3); higher entropy introduces hallucination and false rejections. Treat this as a starting point and A/B-test it on your own labelled set.
  • JSON-mode: Structured output eliminates parsing ambiguity and ensures consistent schema across verdicts.
  • Qwen3-VL: multimodal VLMs are reported in general research (not measured on this task) to reach roughly ~90%+ on document-fraud and phishing benchmarks with screenshot input — treat that as a directional prior, not a promise for your workload, and A/B-test it on your own labelled set. Open-source and EU-hosted on JuiceFactory.

The Verdict Schema

export type Verification = {
  verdict: "pass" | "review" | "reject";
  scamScore: number;                  // 0–100 confidence in fraud
  isRealProduct: boolean;             // Legitimate site vs. scam/parked
  claimsMatch: boolean;               // Do submitter claims align with page?
  sovereignty: {                      // For GDPR/EU-native claims
    dataLocationPlausible: boolean;
    gdprEvidence: boolean;            // Privacy policy present?
    euOwnedEvidence: boolean;         // Company info/imprint/EU signals?
    notes: string;                    // Detailed explanation
  };
  redFlags: string[];                 // Specific threats detected
  summary: string;                    // One-paragraph human-readable verdict
  suggested: {                        // Clean listing fields from actual site
    tagline?: string;
    description?: string;
    category?: string;
    pricing?: string;                 // "Free", "Freemium", "Paid", "Contact"
    dataLocation?: string;            // "EU", "Nordic", "Self-hosted", etc.
    features?: string[];
    useCases?: string[];
  };
};

Real-World Red Flags

The system catches these threats:

ThreatSignalExample
Parked/empty domainbodyText empty or boilerplate; no headingsDomain registered, no content deployed.
Phishing pageLogo present but URL mismatches claimed brand; call-to-action is "log in" with no product descriptionScreenshot shows Slack UI; URL is "slack-verify.herokuapp.com".
Fake sovereignty claimsgdprNative: true but no privacy policy found; or privacy policy redirects outside EUSubmitter claims "EU data residency" but Terms link to AWS-US region notice.
Inflated pricing claimSubmitter says "Free" but page shows "$99/month" or has aggressive upsellReal pricing contradicts submission.
Crypto scam overlaybodyText contains "yield", "APY", "guaranteed returns"Real product is a note-taking app; page mentions DeFi yields.
Login wall, no productScreenshot shows login form; no public product information visibleUser cannot evaluate product without credentials.
Brand impersonationLogo and name closely mimic established brand; different domainPage looks like Notion but URL is "n0tion.ai".

False Positives vs. False Negatives: A Value Choice

Research in content moderation (Automated Content Moderation: A Primer) identifies a fundamental tradeoff:

  • False positive (wrongly reject): A legitimate EU tool gets blocked, costing the vendor time to appeal and harming curator reputation.
  • False negative (wrongly pass): A scam or phishing page ships in the directory, harming users and regulators' trust in curation.

The threshold that separates these is not technical — it's a policy choice. The review verdict exists precisely to defer this choice to humans.

Setting Strategy by Context

For high-trust directories (LaunchRadar):

  • Err toward higher precision (fewer false positives): pass only if evidence strongly supports legitimacy and claims.
  • review for uncertain cases (missing privacy policy, weak imprint, but otherwise plausible).
  • reject only for clear fraud (phishing, parked, crypto overlay).
  • Why? A false positive damages a small vendor; a false negative damages the directory's reputation equally, but vendors can appeal.

For user-facing moderation (e.g., product reviews on a marketplace):

  • Err toward higher recall (fewer false negatives): Catch scams aggressively, escalate borderline cases to human review.
  • Accept more false positives (a seller's review gets hidden temporarily) to protect buyers.
  • Why? The cost of a scam reaching users exceeds the cost of a wrongly-hidden review.

Calibration in Practice

Use the scamScore and redFlags to tune the threshold:

if (verdict === "reject" && scamScore >= 85) {
  // High confidence fraud: auto-reject
  listing.status = "rejected";
} else if (verdict === "reject" && scamScore >= 60) {
  // Moderate confidence: escalate to human
  listing.status = "review";
} else if (verdict === "review") {
  // Uncertain: human decision
  listing.status = "review";
} else {
  // Pass or low-confidence reject
  listing.status = "approved";
}

The model outputs scamScore and redFlags so curators can reason about borderline cases. A score of 65 with a note "missing privacy policy" is different from a score of 65 with "phishing URL pattern" — the latter is higher-stakes. Where you set these numeric cutoffs is a policy choice, not a fixed rule — calibrate them against your own labelled decisions.


Human Curation: Keeping the Loop Closed

Automated detection must not be the final decision. Curators should:

  1. Review all review verdicts before approving or rejecting.
  2. Spot-check pass verdicts (especially early in deployment) to calibrate the model.
  3. Document appeals when vendors dispute rejections. Feedback loops improve the model.

How often you spot-check, how you run appeals, and how frequently you retrain all depend on your volume — a directory taking a handful of submissions a day will sample very differently from one taking hundreds. Start conservative (sample more early on), then relax the cadence as your labelled agreement with the model stabilises.

The summary field in the verdict is designed for curators:

"summary": "Page has privacy policy and EU company imprint (GmbH). 
Screenshots match described features. No immediate red flags. 
Recommend approval — pricing claim 'Freemium' matches web copy."

This narrative, paired with the structured fields, lets a human curator decide in seconds, not hours of manual review.

Feedback Loop

Track curator decisions against model predictions:

  • Curator approved a review verdict: Model was too conservative. Retrain with this as a signal.
  • Curator rejected a pass verdict: Model hallucinated or missed a signal. Debug the input (was the screenshot corrupt? was the text signal incomplete?).

Over time — at a retrain cadence that fits your volume — this feedback tightens the review threshold and reduces false positives without increasing false negatives.


Where JuiceFactory Fits

JuiceFactory is the EU-sovereign, GDPR-compliant AI gateway that hosts Qwen3-VL and other open-source models. If you're still choosing infrastructure, compare EU-hosted vision and LLM providers before you commit. For this workflow:

  • Sovereignty & statelessness: Your detection pipeline runs on EU infrastructure, with no data flowing to US cloud providers. The API is stateless — no server-side retention of your prompts, screenshots, or verdicts.
  • Vision LLM: Qwen3-VL handles multi-modal inputs (screenshot + text); benchmark it on your own fraud set rather than trusting a generic accuracy figure.
  • JSON-mode: Structured, deterministic output (no parsing errors, consistent schema).
  • BYOK (Bring Your Own Key): You control the API key; JuiceFactory doesn't see your listings or verdicts.
  • Scalability: Handle hundreds of submissions per day without rate-limiting; billing per token.

Quick Start

JuiceFactory is OpenAI-compatible — point any OpenAI SDK or fetch at https://api.juicefactory.ai/v1 and swap in your key:

export JUICEFACTORY_API="https://api.juicefactory.ai"
export JUICEFACTORY_API_KEY="your-key-here"

curl -X POST "${JUICEFACTORY_API}/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${JUICEFACTORY_API_KEY}" \
  -d '{
    "model": "qwen3-vl",
    "temperature": 0.2,
    "max_tokens": 1600,
    "response_format": { "type": "json_object" },
    "messages": [
      { "role": "system", "content": "<SYSTEM_PROMPT_HERE>" },
      { "role": "user", "content": [
        { "type": "text", "text": "SUBMITTER CLAIMS:\n..." },
        { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } }
      ]}
    ]
  }'

See Structured Extraction with Vision LLMs and Adversarial Validation for deeper guides on handling edge cases.


Key Takeaways

  1. Multi-modal wins: Screenshot + text + metadata catch fraud that text-only LLMs miss — that's the durable point, independent of any specific accuracy number.

  2. Temperature matters: Low temperature (0.2–0.3) tends to reduce hallucination and improve precision — verify the exact setting on your own set. Use JSON-mode to eliminate parsing ambiguity.

  3. False positives and false negatives are different costs: A wrong reject blocks a vendor; a wrong pass harms users. Choose your threshold based on your curator's risk tolerance, not a generic default.

  4. Humans decide, not the model: The review verdict is your ally. Use it liberally. Feedback from curators on borderline cases trains the next iteration.

  5. Evidence, not assertions: Look for privacy policies, company imprints, European language/market signals. Require proof of sovereignty claims — don't trust a checkbox.

  6. Keep it deterministic: JSON-mode, structured output, and low temperature ensure that the same listing produces the same verdict twice. Curators need consistency to reason about appeals.

  7. EU infrastructure matters: GDPR compliance, no US cloud vendor lock-in, and BYOK mean your listings and verdicts never leave the EU data space.


References & Further Reading


About JuiceFactory: Sovereign EU LLM gateway. Qwen models (text + vision), JSON-mode, BYOK, no US cloud lock-in. juicefactory.ai

Start building: Get a free JuiceFactory API key — no credit card required.


Related guides: EU LLM API Comparison · Multi-Modal AI Assistant · Structured Data Extraction · Vision-LLM Cost Optimization

Related Guides

Try JuiceFactory — Free API Key in 30 Seconds

EU-hosted, zero-retention, OpenAI-compatible. 10,000 free tokens, no credit card.