<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohammed Samaan</title>
    <description>The latest articles on DEV Community by Mohammed Samaan (@mohammed_samaan_b256ef3f5).</description>
    <link>https://dev.to/mohammed_samaan_b256ef3f5</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4168559%2F74f8f494-adea-4170-99bf-c84692c3369b.jpg</url>
      <title>DEV Community: Mohammed Samaan</title>
      <link>https://dev.to/mohammed_samaan_b256ef3f5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohammed_samaan_b256ef3f5"/>
    <language>en</language>
    <item>
      <title>PDF to Markdown on Apify: pdf-text-extractor against pdf-to-markdown-ocr, with prices</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Tue, 27 Oct 2026 18:58:46 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/pdf-to-markdown-on-apify-pdf-text-extractor-against-pdf-to-markdown-ocr-with-prices-3fak</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/pdf-to-markdown-on-apify-pdf-text-extractor-against-pdf-to-markdown-ocr-with-prices-3fak</guid>
      <description>&lt;p&gt;Also published on Medium: &lt;a href="https://medium.com/@samaanmohammed/pdf-to-markdown-on-apify-pdf-text-extractor-against-pdf-to-markdown-ocr-with-prices-e2c42339c0e1" rel="noopener noreferrer"&gt;https://medium.com/@samaanmohammed/pdf-to-markdown-on-apify-pdf-text-extractor-against-pdf-to-markdown-ocr-with-prices-e2c42339c0e1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We built one of the two tools compared here. Prices and user counts are from the public Apify pages on 27 October 2026.&lt;/p&gt;

&lt;p&gt;If you feed PDFs to a retrieval pipeline or an LLM, you need clean Markdown, the page structure and a way to handle scanned pages. Two Apify actors do this. The one with more users is &lt;code&gt;gochujang/pdf-text-extractor&lt;/code&gt;. The other is &lt;code&gt;leadharbor/pdf-to-markdown-ocr&lt;/code&gt;, which is ours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The leader
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gochujang/pdf-text-extractor&lt;/code&gt; had 273 total users and 2,080 runs. Its listing says it extracts text, Markdown or RAG chunks, detects tables, and can optionally OCR scanned pages.&lt;/p&gt;

&lt;p&gt;Its current price, in effect since 22 September 2026, is a start fee of $0.001, $0.02 per PDF and $0.001 per page. The pricing data has no separate OCR charge, so the listing does not tell you what an OCR page costs. Check the actor page before you run it on scans.&lt;/p&gt;

&lt;h2&gt;
  
  
  pdf-to-markdown-ocr
&lt;/h2&gt;

&lt;p&gt;It returns one Markdown document per PDF and one entry per page. It also returns heading-based chunks with an approximate token count (characters divided by four) and a quality report for each file.&lt;/p&gt;

&lt;p&gt;Pages with a text layer are read directly. Pages that are only pictures go through OCR. English and Arabic come built in. Any other OCR language is downloaded when a run needs it and is marked experimental. Arabic text comes back in reading order, first word first.&lt;/p&gt;

&lt;p&gt;The quality report sets &lt;code&gt;needsReview&lt;/code&gt; to true when an OCR page has a confidence under 70, when a page fails a text check, or when a page could not be read. A false value does not mean the file is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Price
&lt;/h2&gt;

&lt;p&gt;$0.004 per PDF converted and $0.007 per page read by OCR. Pages with a text layer add nothing per page. A file that fails, or a partial file, is not charged the PDF fee. Our README gives this example: a 20-page scan costs 20 x $0.007 + $0.004 = $0.144.&lt;/p&gt;

&lt;p&gt;The same job at the published prices (our arithmetic, not measured runs):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;pdf-text-extractor&lt;/th&gt;
&lt;th&gt;pdf-to-markdown-ocr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10-page text PDF&lt;/td&gt;
&lt;td&gt;$0.031&lt;/td&gt;
&lt;td&gt;$0.004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100-page text PDF&lt;/td&gt;
&lt;td&gt;$0.121&lt;/td&gt;
&lt;td&gt;$0.004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20-page scan, every page OCR&lt;/td&gt;
&lt;td&gt;not stated in the listing&lt;/td&gt;
&lt;td&gt;$0.144&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The leader figures assume one PDF per run: $0.001 start, $0.02 for the PDF, and $0.001 for each page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality
&lt;/h2&gt;

&lt;p&gt;Our own benchmark uses 8 files, run locally with the same code as the Apify image. On an Arabic text PDF, word F1 was 0.987 raw and 1.000 with the page-marker lines removed. The scans are clean renders and the set is small, so this measures those files only. We have not run the leader on these files, so we make no quality claim against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one to pick
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Text PDFs, many files, cost matters most: pdf-to-markdown-ocr is cheaper per file at these prices.&lt;/li&gt;
&lt;li&gt;You want an actor with a longer public record: the leader has more users and more runs.&lt;/li&gt;
&lt;li&gt;Scanned pages, and you want a confidence score for each page: pdf-to-markdown-ocr reports one. Check the leader's OCR behaviour and price before you pick it for scans.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Up to 100 links per run, 25 MB per file. The default is 100 pages per file, and the maximum is 500.&lt;/li&gt;
&lt;li&gt;A conversion that makes no progress for 3 minutes, or runs past 30 minutes in total, returns the pages it finished, marked partial.&lt;/li&gt;
&lt;li&gt;Skew up to 7 degrees is straightened. Stronger tilts, curved pages and mixed orientation on one page are not handled.&lt;/li&gt;
&lt;li&gt;We have 2 users so far and no outside reviews. Test it on your own files first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it: &lt;a href="https://apify.com/leadharbor/pdf-to-markdown-ocr" rel="noopener noreferrer"&gt;https://apify.com/leadharbor/pdf-to-markdown-ocr&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apify</category>
      <category>pdf</category>
      <category>ocr</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>PHP2Shell: a client-proof patch checklist for freelancers (CVE-2026-109618 / 109619)</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Mon, 26 Oct 2026 08:48:45 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/php2shell-a-client-proof-patch-checklist-for-freelancers-cve-2026-109618-109619-311f</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/php2shell-a-client-proof-patch-checklist-for-freelancers-cve-2026-109618-109619-311f</guid>
      <description>&lt;p&gt;Free checklist, written 26 Oct 2026. It is a technical checklist, not legal advice, not a security audit, and no guarantee that a server is safe.&lt;br&gt;
For freelancers and small agencies who look after other people's PHP and WordPress servers.&lt;br&gt;
Version 1.1 · written 26 Oct 2026 · facts are as reported by the sources listed at the end, each with a read date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this is:&lt;/strong&gt; a checklist you can run on a server (a guess: about 30 minutes for a simple one) and the words to send your client afterwards. It is not legal advice, not a security audit, and not a guarantee that a server is safe. It does not replace updating PHP; updating is the only complete fix (Tenable, citing PHP).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before you start:&lt;/strong&gt; only work on servers you are contracted to manage, get the client's written go-ahead before you change settings, take a site offline or restore a backup, and keep a written record of every command you run and every change you make. The commands below only read client data, except the settings and updates in Steps 3 and 4. The file search in section 4 writes one results file into your own home folder; delete it when you are done.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. What happened (as reported by the sources)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On 21 Oct 2026 the PHP project fixed two critical flaws, &lt;strong&gt;CVE-2026-109618&lt;/strong&gt; and &lt;strong&gt;CVE-2026-109619&lt;/strong&gt;, together called "php2shell". Tenable, citing the PHP security team, gives both CVSS v4.0 &lt;strong&gt;9.2&lt;/strong&gt; (an earlier circulated score of 10.0 was wrong) and says an unauthenticated remote attacker can exploit them.&lt;/li&gt;
&lt;li&gt;Amazon's honeypots recorded a first attempt on &lt;strong&gt;17 Oct&lt;/strong&gt;, four days before disclosure, and more on 21 Oct. Amazon says php2shell now sees broad exploitation &lt;strong&gt;attempts&lt;/strong&gt; in the wild. CISA said it had &lt;strong&gt;not observed successful exploitation&lt;/strong&gt; at publication; CISA revised its alert on 23 Oct, so that statement may be out of date. As of 23 Oct neither CVE was in CISA's KEV catalog (Tenable).&lt;/li&gt;
&lt;li&gt;CISA says all PHP installations serving web requests are affected (Apache mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed). CISA notes that PHP considers mod_php the highest risk.&lt;/li&gt;
&lt;li&gt;Hostinger says the setting &lt;code&gt;session.upload_progress.enabled = Off&lt;/code&gt; also protects against a further issue, &lt;strong&gt;CVE-2026-115560&lt;/strong&gt;. We did not verify that CVE ourselves; check its status with your vendor.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  2. Is this server affected?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PHP branch&lt;/th&gt;
&lt;th&gt;Status (Tenable, read 26 Oct)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8.5.x before 8.5.12, 8.4.x before 8.4.27, 8.3.x before 8.3.36, 8.2.x before 8.2.35&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Affected.&lt;/strong&gt; Fixed in 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 (CISA names the same four; php.net's release feed lists each as a security release dated 21 Oct 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.4 to 8.1&lt;/td&gt;
&lt;td&gt;No official release; "minimal source backports from the PHP security team". Rely on your OS vendor's package and their advisory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.4 to 7.3&lt;/td&gt;
&lt;td&gt;End of life, no fix from the PHP project&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Do not trust &lt;code&gt;php -v&lt;/code&gt; alone.&lt;/strong&gt; It reports the command-line binary, which can differ from the PHP that serves web requests (FPM, mod_php, LiteSpeed). Packaged and hosted builds can also be fixed without the version number changing (Hostinger says so for its managed hosting).&lt;/p&gt;
&lt;h2&gt;
  
  
  3. The triage, per server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: find every PHP on the box&lt;/strong&gt; (CISA: inventory all installs including embedded ones, internet-facing first).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which &lt;span class="nt"&gt;-a&lt;/span&gt; php php-fpm php-cgi
php &lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; php-fpm &lt;span class="nt"&gt;-v&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;       &lt;span class="c"&gt;# on Debian/Ubuntu the FPM binary is versioned, for example php-fpm8.3; the dpkg line below lists it&lt;/span&gt;
apachectl &lt;span class="nt"&gt;-M&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; php          &lt;span class="c"&gt;# on RHEL-family use: httpd -M | grep -i php&lt;/span&gt;
ps &lt;span class="nt"&gt;-eo&lt;/span&gt; user,pid,ppid,etime,cmd &lt;span class="nt"&gt;--forest&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'php-fpm|php-cgi|lsphp|frankenphp|httpd|apache2'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-40&lt;/span&gt;
dpkg &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s1"&gt;'php*'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^ii'&lt;/span&gt;         &lt;span class="c"&gt;# Debian / Ubuntu: every installed PHP package&lt;/span&gt;
rpm &lt;span class="nt"&gt;-qa&lt;/span&gt; &lt;span class="s1"&gt;'php*'&lt;/span&gt;                      &lt;span class="c"&gt;# RHEL / Alma / Rocky / Remi: every installed PHP package&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors here matter; do not hide them. A command that is missing on your system is itself information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: is each installed package patched?&lt;/strong&gt; Ask the package. Do this for every package from Step 1, not just one version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Debian / Ubuntu (needs network access)&lt;/span&gt;
apt changelog php8.3-fpm | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-m3&lt;/span&gt; 109618      &lt;span class="c"&gt;# change php8.3-fpm to each package you found&lt;/span&gt;
&lt;span class="c"&gt;# RHEL / Alma / Rocky (package names vary, for example php-fpm or php83-php-fpm)&lt;/span&gt;
rpm &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--changelog&lt;/span&gt; php-fpm | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-m3&lt;/span&gt; 109618
dnf updateinfo list &lt;span class="nt"&gt;--cve&lt;/span&gt; CVE-2026-109618          &lt;span class="c"&gt;# if your dnf supports it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the changelog names the CVE, the package contains a fix. &lt;strong&gt;A missing CVE line does not mean unpatched&lt;/strong&gt;, and a CVE line does not mean the running process has it: the service must have been &lt;strong&gt;restarted&lt;/strong&gt; after the update. If you cannot tell, check your OS vendor's security advisory before telling a client anything.&lt;br&gt;
Managed hosts: Hostinger states that a PHP build date of &lt;strong&gt;21 Oct 2026 or later&lt;/strong&gt; means its fix is in. That rule is Hostinger's; other hosts have their own, so ask them (section 7).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: interim settings, only if you cannot update yet, and only with the client's consent.&lt;/strong&gt; They reduce exposure; they do not make the server safe (Tenable).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For CVE-2026-109619: &lt;code&gt;session.upload_progress.enabled = 0&lt;/code&gt; in php.ini or the PHP-FPM pool config. Setting it with &lt;code&gt;ini_set&lt;/code&gt; in code does &lt;strong&gt;not&lt;/strong&gt; work (Hostinger). &lt;strong&gt;Side effect:&lt;/strong&gt; applications that show upload progress bars may stop working.&lt;/li&gt;
&lt;li&gt;For CVE-2026-109618: Tenable, quoting PHP, lists &lt;code&gt;memory_limit=-1&lt;/code&gt; set so applications cannot override it. &lt;strong&gt;Warning from us:&lt;/strong&gt; an unlimited memory limit lets one runaway request exhaust the server's memory and take down every site on it. Use it only on a server you control, with consent, and prefer a container or cgroup memory cap alongside it (Tenable suggests one). On PHP 8.5 Tenable also lists &lt;code&gt;fatal_error_backtraces=0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Amazon also suggests blocking multipart file uploads for systems that cannot be patched quickly, after you assess the impact on the application (many sites need uploads).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart every PHP worker&lt;/strong&gt; after any change (FPM, Apache, LiteSpeed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4: update.&lt;/strong&gt; Move to a fixed release or your OS vendor's patched package, restart, then repeat Step 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: PHP 8.1 or older that cannot be updated.&lt;/strong&gt; CISA's recommendation is to take such systems offline &lt;strong&gt;until they are patched or upgraded&lt;/strong&gt;. Taking a client's site offline is the client's decision; give them the choice in writing. PHP 8.2 security support also ends on &lt;strong&gt;31 Dec 2026&lt;/strong&gt; (Hostinger; php.net), so plan the move now.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Check for signs of compromise
&lt;/h2&gt;

&lt;p&gt;The public sources give very little to search for. Here is all of it, and how to use it honestly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start your review from 17 Oct 2026, not from 21 Oct&lt;/strong&gt; (Amazon).&lt;/li&gt;
&lt;li&gt;Look for &lt;strong&gt;POST requests containing the string &lt;code&gt;PHP_SESSION_UPLOAD_PROGRESS&lt;/code&gt;&lt;/strong&gt; in form uploads (Amazon). Standard access logs do not record POST bodies, so this needs a WAF or ModSecurity audit log. If you have none, say so in your client report instead of claiming the server is clean.&lt;/li&gt;
&lt;li&gt;Look for unexpected process execution and unexpected file changes on web servers (Amazon).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# GNU find (Debian / RHEL; not BusyBox, Alpine or macOS). Times follow the server's timezone.&lt;/span&gt;
&lt;span class="c"&gt;# Files changed since 17 Oct 2026 with extensions attackers commonly use. Adjust the path. Read-only.&lt;/span&gt;
&lt;span class="nb"&gt;umask &lt;/span&gt;077   &lt;span class="c"&gt;# results file readable by you only&lt;/span&gt;
&lt;span class="nb"&gt;nice &lt;/span&gt;find /var/www &lt;span class="nt"&gt;-xdev&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="se"&gt;\(&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.php'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.phtml'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.phar'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.inc'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'.htaccess'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'.user.ini'&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-newermt&lt;/span&gt; &lt;span class="s1"&gt;'2026-10-17'&lt;/span&gt; &lt;span class="nt"&gt;-printf&lt;/span&gt; &lt;span class="s1"&gt;'%TY-%Tm-%Td %TH:%TM  %u  %p\n'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/changed-since-17oct.txt"&lt;/span&gt;
&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/changed-since-17oct.txt"&lt;/span&gt;        &lt;span class="c"&gt;# then read the whole file; delete it when finished&lt;/span&gt;
&lt;span class="c"&gt;# PHP processes' children (look for shells or unexpected binaries under php-fpm or apache)&lt;/span&gt;
ps &lt;span class="nt"&gt;-eo&lt;/span&gt; user,pid,ppid,etime,cmd &lt;span class="nt"&gt;--forest&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Limits you must state to the client: file times can be forged and legitimate deploys also change files, and files with other extensions or in other paths are not covered. The web user is &lt;code&gt;www-data&lt;/code&gt; on Debian, &lt;code&gt;apache&lt;/code&gt; or &lt;code&gt;nginx&lt;/code&gt; on RHEL, and a per-account user on cPanel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon's honeypot saw attempts from 103.216.220.92 (17 Oct) and 31.223.184.166, 37.19.200.5, 134.209.159.64, 103.114.163.188, 95.217.98.37 (21 Oct). These are shared anonymising infrastructure. Investigate hits from them; do not simply block them (Amazon).&lt;/li&gt;
&lt;li&gt;A clean result from these checks means "we found nothing by these checks", not "we are safe".&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. If you find something
&lt;/h2&gt;

&lt;p&gt;Tell the client immediately and let them decide. With their written go-ahead and after a fresh backup of the current state (keep it as evidence): take the site out of service, restore from a backup made before 17 Oct (note this can lose newer client data), update PHP, rotate every credential the site could read (database, API keys, admin and hosting passwords), and report what you found in writing. If the client is regulated they may have notification duties; that is for their lawyer, not this pack.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. What to tell the client
&lt;/h2&gt;

&lt;p&gt;Use the one-page report and the emails below. Rules: say what you checked, what you changed, what you could not check, and the date. Never write "secure" or "hack-proof".&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Ask your host these four questions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Which PHP build is my account running, and does it include the fix for CVE-2026-109618 and CVE-2026-109619? How can I verify that myself?&lt;/li&gt;
&lt;li&gt;When did you roll it out, and was every PHP version on my plan patched, including 8.1 and older?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;session.upload_progress.enabled&lt;/code&gt; off at server level?&lt;/li&gt;
&lt;li&gt;Do you keep WAF or audit logs I can search from 17 Oct onward?
Reference point: Hostinger reports it completed its rollout on 22 Oct at 06:44 UTC. We did not verify any other host's status.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  9. One-page client report (copy it)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Client:&lt;/strong&gt; [name] · &lt;strong&gt;Site(s):&lt;/strong&gt; [domains] · &lt;strong&gt;Server:&lt;/strong&gt; [host / IP] · &lt;strong&gt;Checked by:&lt;/strong&gt; [your name] · &lt;strong&gt;Date:&lt;/strong&gt; [date] · &lt;strong&gt;Authorised by:&lt;/strong&gt; [client name, date of written go-ahead]&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary (one sentence)
&lt;/h2&gt;

&lt;p&gt;[Pick one and delete the others]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per the package changelog / host statement dated &lt;a href="https://dev.tonot%20independently%20tested"&gt;date&lt;/a&gt;, your server runs a PHP build that includes the fix, and the service was restarted on [date].&lt;/li&gt;
&lt;li&gt;Your server was running a vulnerable PHP build. We updated it on [date], restarted the service and re-checked the package.&lt;/li&gt;
&lt;li&gt;Your host has not confirmed a fix. With your consent we applied temporary settings and asked them to confirm. The risk remains until they do.&lt;/li&gt;
&lt;li&gt;Your server runs PHP [version], which the PHP project no longer fixes. We recommend moving it by [date]; taking it offline until then is your decision.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we checked
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PHP builds present (CLI and web)&lt;/td&gt;
&lt;td&gt;[list]&lt;/td&gt;
&lt;td&gt;commands run, date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fix present in the package&lt;/td&gt;
&lt;td&gt;yes / no / could not verify&lt;/td&gt;
&lt;td&gt;changelog or host statement, and restart date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary settings applied (&lt;code&gt;session.upload_progress.enabled = 0&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;yes / no / not applied&lt;/td&gt;
&lt;td&gt;file and restart date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Files changed since 17 Oct 2026&lt;/td&gt;
&lt;td&gt;none found by this search (limits below) / [list]&lt;/td&gt;
&lt;td&gt;file search of [paths and extensions]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unexpected processes&lt;/td&gt;
&lt;td&gt;none seen at the time / [list]&lt;/td&gt;
&lt;td&gt;process list, time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web firewall or audit log available for 17 Oct onward&lt;/td&gt;
&lt;td&gt;yes / no&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What we changed
&lt;/h2&gt;

&lt;p&gt;[date, time, what, who]&lt;/p&gt;

&lt;h2&gt;
  
  
  What we could not check
&lt;/h2&gt;

&lt;p&gt;[for example: no request-body logs, so we cannot rule out attempts; file times can be forged; the host did not answer question 3]&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means
&lt;/h2&gt;

&lt;p&gt;Finding nothing is not proof that nothing happened. The first attack attempts were reported on 17 Oct 2026. [one honest sentence about the residual risk]&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;[action, cost] by [date]&lt;/li&gt;
&lt;li&gt;[action, cost] by [date]&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;This is a technical check, not legal or insurance advice.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Emails (copy and edit)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A.Check completed (to your client)
&lt;/h3&gt;

&lt;p&gt;Subject: Your website server: PHP security check completed&lt;/p&gt;

&lt;p&gt;Hi [name],&lt;br&gt;
On [date] we checked your server for the PHP vulnerability announced on 21 Oct 2026 (CVE-2026-109618 and CVE-2026-109619). [One sentence from the report summary.] The attached one-page report lists what we checked and changed.&lt;br&gt;
One honest limit: [for example: we do not have request logs from before 21 Oct, so we cannot prove nothing was attempted]. We recommend [next step, with cost] by [date].&lt;br&gt;
[your name]&lt;/p&gt;

&lt;h3&gt;
  
  
  B.Your host has not confirmed the fix (to your client)
&lt;/h3&gt;

&lt;p&gt;Subject: Decision needed: your hosting provider has not confirmed the PHP fix&lt;/p&gt;

&lt;p&gt;Hi [name],&lt;br&gt;
A serious PHP vulnerability was announced on 21 Oct 2026, and Amazon reported exploitation attempts from 17 Oct. Your host has not yet confirmed that your plan is fixed. We asked them on [date] and have not had a clear answer.&lt;br&gt;
What we have done meanwhile, with your earlier consent: [temporary settings]. These reduce the risk; they do not remove it.&lt;br&gt;
Options: [wait until X / move to a host that confirms / update by Y]. Each has a cost: [cost]. Please reply with the option you choose and the cost you approve, in writing, and we will start only the work you name.&lt;br&gt;
[your name]&lt;/p&gt;

&lt;h3&gt;
  
  
  C.To the host's support
&lt;/h3&gt;

&lt;p&gt;Subject: Please confirm PHP2Shell fix for account [id]&lt;/p&gt;

&lt;p&gt;Hello,&lt;br&gt;
Please confirm for the account [id]: (1) which PHP build it runs and whether it includes the fix for CVE-2026-109618 and CVE-2026-109619, and how we can verify that ourselves; (2) the rollout date and whether all PHP versions on the plan, including 8.1 and older, are covered; (3) whether session.upload_progress.enabled is off at server level; (4) whether WAF or audit logs from 17 Oct onward are available to us.&lt;br&gt;
Thank you,&lt;br&gt;
[your name]&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources (read 26 Oct 2026)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CISA alert, 21 Oct 2026 (revised 23 Oct): &lt;a href="https://www.cisa.gov/news-events/alerts/2026/10/21/critical-vulnerabilities-php-require-immediate-patching" rel="noopener noreferrer"&gt;https://www.cisa.gov/news-events/alerts/2026/10/21/critical-vulnerabilities-php-require-immediate-patching&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tenable FAQ: &lt;a href="https://www.tenable.com/blog/php2shell-cve-2026-109618-cve-2026-109619-frequently-asked-questions-about-critical-php-remote" rel="noopener noreferrer"&gt;https://www.tenable.com/blog/php2shell-cve-2026-109618-cve-2026-109619-frequently-asked-questions-about-critical-php-remote&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Amazon Threat Intelligence: &lt;a href="https://aws.amazon.com/blogs/security/amazon-threat-intelligence-identifies-php2shell-exploitation-prior-to-public-disclosure-in-madpot/" rel="noopener noreferrer"&gt;https://aws.amazon.com/blogs/security/amazon-threat-intelligence-identifies-php2shell-exploitation-prior-to-public-disclosure-in-madpot/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hostinger: &lt;a href="https://www.hostinger.com/blog/protecting-php2shell/" rel="noopener noreferrer"&gt;https://www.hostinger.com/blog/protecting-php2shell/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;php.net release feed, read 26 Oct: &lt;a href="https://www.php.net/releases/index.php?json&amp;amp;version=8.4" rel="noopener noreferrer"&gt;https://www.php.net/releases/index.php?json&amp;amp;version=8.4&lt;/a&gt; (8.4.27, 21 Oct 2026, tagged security; the same query with version=8.5, 8.3 and 8.2 returns 8.5.12, 8.3.36 and 8.2.35, all 21 Oct 2026) and &lt;a href="https://www.php.net/supported-versions.php" rel="noopener noreferrer"&gt;https://www.php.net/supported-versions.php&lt;/a&gt;
Not checked by us: your OS vendor's advisories, any host other than Hostinger, the KEV catalog after 23 Oct, and the commands on every distribution (they were reviewed, not run on a client server). Check those before you rely on this pack.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>wordpress</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12: the version table for the 21 Oct 2026 security releases</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Thu, 22 Oct 2026 14:50:35 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/php-8235-8336-8427-8512-the-version-table-for-the-21-oct-2026-security-releases-3b4e</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/php-8235-8336-8427-8512-the-version-table-for-the-21-oct-2026-security-releases-3b4e</guid>
      <description>&lt;p&gt;On 21 October 2026 PHP published four releases tagged "security": 8.5.12, 8.4.27, 8.3.36 and 8.2.35. They fix two critical remote-code-execution flaws, CVE-2026-109618 and CVE-2026-109619 (the OSV database lists the same four versions as fixed). PHP 8.1 and older got no official fixed release.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Branch&lt;/th&gt;
&lt;th&gt;Fixed in&lt;/th&gt;
&lt;th&gt;Support ends (endoflife.date, read 22 Oct 2026)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;td&gt;8.5.12&lt;/td&gt;
&lt;td&gt;2029-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.4&lt;/td&gt;
&lt;td&gt;8.4.27&lt;/td&gt;
&lt;td&gt;2028-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.3&lt;/td&gt;
&lt;td&gt;8.3.36&lt;/td&gt;
&lt;td&gt;2027-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.2&lt;/td&gt;
&lt;td&gt;8.2.35&lt;/td&gt;
&lt;td&gt;2026-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.1 and older&lt;/td&gt;
&lt;td&gt;no official fix&lt;/td&gt;
&lt;td&gt;8.1 ended 2025-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What the sources say about exploitation: Rapid7 (21 October) says a viable exploit is expected to be made public soon, exploitation in the wild is expected, and it recommends updating on an emergency basis. Tenable reports that Amazon Threat Intelligence observed an exploitation attempt on 17 October and more on 21 October, and that Amazon says it is unclear whether those attempts would have succeeded against real systems. Reports differ between sources and change quickly, so check php.net and your host's notices for the current status.&lt;/p&gt;

&lt;p&gt;Two practical points when you check your own servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the version from the PHP that serves the site. The command-line &lt;code&gt;php -v&lt;/code&gt; can differ from PHP-FPM, and FPM must be restarted after an update.&lt;/li&gt;
&lt;li&gt;Linux distribution packages can include a fix without changing the version number, so check your distribution's security notice before you decide a server is behind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it helps: I made a small free page where you type a version and it says whether it is at or above the fixed release and when its branch ends: &lt;a href="https://samaanmohammed-art.github.io/php-patch-check/" rel="noopener noreferrer"&gt;https://samaanmohammed-art.github.io/php-patch-check/&lt;/a&gt; . It only compares the number you type; it connects to nothing and does not scan or protect anything. For agencies with many sites I also made a $19 spreadsheet-and-email kit (disclosure: both are mine): &lt;a href="https://samaanmohammed.gumroad.com/l/xvsyxe" rel="noopener noreferrer"&gt;https://samaanmohammed.gumroad.com/l/xvsyxe&lt;/a&gt; . Data as of 22 October 2026; no security or legal advice.&lt;/p&gt;

</description>
      <category>php</category>
      <category>security</category>
      <category>webdev</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>An SPF, DKIM and DMARC audit as one API call</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Mon, 19 Oct 2026 14:49:19 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/an-spf-dkim-and-dmarc-audit-as-one-api-call-1gj8</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/an-spf-dkim-and-dmarc-audit-as-one-api-call-1gj8</guid>
      <description>&lt;p&gt;Mail that lands in spam is often a DNS problem: a missing DMARC record, an SPF record that uses too many lookups, no DKIM key. Checking all of that by hand with dig gets old fast.&lt;/p&gt;

&lt;p&gt;Here is the curl version, using the real gateway path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://email-dns-health-spf-dkim-dmarc.p.rapidapi.com/v1/email-dns?domain=google.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-host: email-dns-health-spf-dkim-dmarc.p.rapidapi.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-key: YOUR_RAPIDAPI_KEY'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint does the lookups for a &lt;code&gt;domain&lt;/code&gt; and returns MX, SPF, DMARC, DKIM, an overall &lt;code&gt;grade&lt;/code&gt; and a list of &lt;code&gt;issues&lt;/code&gt; ranked by severity. No mail is sent. Real capture for google.com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"grade"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"good"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"smtp.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"null_mx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"present"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v=spf1 include:_spf.google.com ~all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"multiple_records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"softfail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"includes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"_spf.google.com"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dns_lookups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dmarc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"present"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subdomain_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"percent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aggregate_reports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mailto:mailauth-reports@google.com"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forensic_reports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dkim_alignment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"spf_alignment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dkim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"selectors_found"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"selector1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"selector2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"k1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"k2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"s1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"s2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"dkim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mandrill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"smtp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"zoho"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mxvault"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"issues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No DKIM key found on common selectors. This is not proof DKIM is missing: your provider may use a custom selector."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Trimmed: the &lt;code&gt;mta_sts&lt;/code&gt;, &lt;code&gt;tls_rpt&lt;/code&gt; and &lt;code&gt;bimi&lt;/code&gt; fields are cut.)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;grade&lt;/code&gt; is &lt;code&gt;good&lt;/code&gt;, &lt;code&gt;fair&lt;/code&gt; or &lt;code&gt;poor&lt;/code&gt;, and each entry in &lt;code&gt;issues&lt;/code&gt; has a severity of &lt;code&gt;high&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;low&lt;/code&gt; or &lt;code&gt;info&lt;/code&gt;. In the capture, SPF is present with a softfail &lt;code&gt;all&lt;/code&gt;, DMARC has &lt;code&gt;policy: reject&lt;/code&gt;, and the only issue is the low-severity DKIM note. The SPF object includes &lt;code&gt;dns_lookups&lt;/code&gt;, which matters because SPF allows at most 10 lookups, and the code raises a high-severity issue when a record needs more. That check alone catches a classic silent failure. Run it before a campaign, or in a cron job across the domains you send from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits worth knowing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DKIM is checked on a fixed list of common selectors only (see &lt;code&gt;dkim.checked&lt;/code&gt;). As the issue message says, finding none is not proof DKIM is missing: google.com above shows &lt;code&gt;selectors_found: []&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Everything comes from DNS, so it reports what is published, not whether your mail actually passes at a receiver.&lt;/li&gt;
&lt;li&gt;If the DNS lookup itself fails you get a 502 ("DNS lookup failed. Try again later."); a missing or invalid &lt;code&gt;domain&lt;/code&gt; is a 400.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Print the grade and any issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://email-dns-health-spf-dkim-dmarc.p.rapidapi.com/v1/email-dns?domain=google.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email-dns-health-spf-dkim-dmarc.p.rapidapi.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grade&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Listing and playground: &lt;a href="https://rapidapi.com/samaanmohammed/api/email-dns-health-spf-dkim-dmarc" rel="noopener noreferrer"&gt;https://rapidapi.com/samaanmohammed/api/email-dns-health-spf-dkim-dmarc&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>email</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What an MX-only email check can and cannot tell you</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Wed, 07 Oct 2026 10:45:13 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/what-an-mx-only-email-check-can-and-cannot-tell-you-1oj6</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/what-an-mx-only-email-check-can-and-cannot-tell-you-1oj6</guid>
      <description>&lt;p&gt;Bad addresses at signup cost you bounces and sender reputation. Full mailbox verification services dial the recipient's mail server to ask whether the mailbox exists. This API does not, and that matters for how you use it. Here is what it returns and where it stops.&lt;/p&gt;

&lt;p&gt;It sits next to two other APIs from the same account. The Disposable Email Checker is the list-only version (&lt;a href="https://dev.to/mohammed_samaan_b256ef3f5/stop-mailinator-signups-with-one-get-request-5dm1"&gt;Stop Mailinator signups with one GET request&lt;/a&gt;), and Domain Trust Score judges the domain (&lt;a href="https://dev.to/mohammed_samaan_b256ef3f5/scoring-an-unknown-domain-0-to-100-from-public-signals-with-every-penalty-documented-d6g"&gt;Scoring an unknown domain 0 to 100&lt;/a&gt;). This one checks the address itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shortest working call
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://email-verifier38.p.rapidapi.com/v1/verify?email=test@gmail.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-host: email-verifier38.p.rapidapi.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-key: YOUR_RAPIDAPI_KEY'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript (Node 18+):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://email-verifier38.p.rapidapi.com/v1/verify?email=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email-verifier38.p.rapidapi.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disposable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://email-verifier38.p.rapidapi.com/v1/verify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test@gmail.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email-verifier38.p.rapidapi.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invalid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;disposable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The response, field by field
&lt;/h2&gt;

&lt;p&gt;Captured from the live API on 7 Oct 2026 (HTTP 200, 607 bytes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mx_only_no_smtp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason_detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Domain accepts mail. This API is MX-only — the mailbox itself was not dialed (SMTP port 25 is blocked on serverless platforms)."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"syntax_valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mx_found"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mx_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gmail-smtp-in.l.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_disposable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_free_provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"has_tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"base_email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"typo_suggestion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain_has_spf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain_has_dmarc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"checked_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-07T10:00:52.056Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; is one of &lt;code&gt;valid&lt;/code&gt;, &lt;code&gt;invalid&lt;/code&gt;, &lt;code&gt;disposable&lt;/code&gt;, &lt;code&gt;risky&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt;. &lt;code&gt;score&lt;/code&gt; runs from 0 to 100.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reason&lt;/code&gt; and &lt;code&gt;reason_detail&lt;/code&gt; explain the verdict. Here the domain accepts mail but the mailbox was not contacted, so the answer is &lt;code&gt;unknown&lt;/code&gt;, not &lt;code&gt;valid&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;syntax_valid&lt;/code&gt;, &lt;code&gt;domain&lt;/code&gt;, &lt;code&gt;mx_found&lt;/code&gt; and &lt;code&gt;mx_host&lt;/code&gt; are the syntax and DNS checks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_disposable&lt;/code&gt;, &lt;code&gt;is_role&lt;/code&gt; (such as &lt;code&gt;info@&lt;/code&gt;) and &lt;code&gt;is_free_provider&lt;/code&gt; are separate booleans. &lt;code&gt;has_tag&lt;/code&gt; and &lt;code&gt;base_email&lt;/code&gt; handle plus-addressing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;typo_suggestion&lt;/code&gt; offers a correction for misspelled domains, or &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;domain_has_spf&lt;/code&gt; and &lt;code&gt;domain_has_dmarc&lt;/code&gt; describe the domain's DNS, not the mailbox.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;duration_ms&lt;/code&gt; is the server-side time (9 ms here, from the response itself). The playground round trip was about 1.5 s.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;meta.user&lt;/code&gt; holds the caller's account name, shown as &lt;code&gt;"..."&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two more captures from the same day, with the same 21 keys. &lt;code&gt;someone@mailinator.com&lt;/code&gt; returned &lt;code&gt;status: "disposable"&lt;/code&gt;, &lt;code&gt;score: 5&lt;/code&gt;, &lt;code&gt;reason: "disposable_domain"&lt;/code&gt;, &lt;code&gt;mx_found: false&lt;/code&gt;. &lt;code&gt;not-an-email&lt;/code&gt; returned &lt;code&gt;status: "invalid"&lt;/code&gt;, &lt;code&gt;score: 0&lt;/code&gt;, &lt;code&gt;reason: "bad_syntax"&lt;/code&gt;, &lt;code&gt;syntax_valid: false&lt;/code&gt; and &lt;code&gt;domain: null&lt;/code&gt;. Both were HTTP 200, so a bad address is a result and not an error status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it at signup
&lt;/h2&gt;

&lt;p&gt;Reject &lt;code&gt;invalid&lt;/code&gt; and &lt;code&gt;disposable&lt;/code&gt;, accept the rest, and confirm with a real confirmation email later. Do not reject &lt;code&gt;unknown&lt;/code&gt;, because it is the normal answer for a good Gmail address.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It never contacts the mailbox. SMTP port 25 is blocked on serverless platforms, so this API cannot tell you a specific mailbox exists.&lt;/li&gt;
&lt;li&gt;It does not detect catch-all domains.&lt;/li&gt;
&lt;li&gt;It cannot promise an address will receive mail or will not bounce. &lt;code&gt;valid&lt;/code&gt; means the checks it runs passed, nothing more.&lt;/li&gt;
&lt;li&gt;A single GET checks one address. A POST to &lt;code&gt;/v1/verify&lt;/code&gt; with an &lt;code&gt;emails&lt;/code&gt; array checks a small batch, with a maximum of 10 per request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;p&gt;A malformed address is a normal 200 with &lt;code&gt;status: "invalid"&lt;/code&gt;, as shown above. Gateway failures such as a missing or wrong key, or a used-up quota, return RapidAPI's own error before the request reaches the API. I did not re-run other error cases for this post, so check the listing's endpoint documentation for the current ones.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;The address was checked, whatever the verdict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-2xx&lt;/td&gt;
&lt;td&gt;Gateway or API failure. Throw, log, and let the user continue rather than blocking signup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;The free Basic plan on the listing currently shows 300 requests per month. Pro is $19 per month for 3,000.&lt;/p&gt;

&lt;p&gt;Listing and playground: &lt;a href="https://rapidapi.com/samaanmohammed/api/email-verifier38" rel="noopener noreferrer"&gt;https://rapidapi.com/samaanmohammed/api/email-verifier38&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>email</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Scoring an unknown domain 0 to 100 from public signals, with every penalty documented</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Wed, 07 Oct 2026 10:13:03 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/scoring-an-unknown-domain-0-to-100-from-public-signals-with-every-penalty-documented-d6g</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/scoring-an-unknown-domain-0-to-100-from-public-signals-with-every-penalty-documented-d6g</guid>
      <description>&lt;p&gt;A lead or signup arrives from a domain you have never seen. Is it a throwaway, a week-old registration, or a company with a valid certificate and a DMARC policy? Checking that by hand means five lookups. This API runs them in one call and returns a score plus the reasons.&lt;/p&gt;

&lt;p&gt;If you only need the disposable-domain part, the Disposable Email Checker from the same account does just that: &lt;a href="https://dev.to/mohammed_samaan_b256ef3f5/stop-mailinator-signups-with-one-get-request-5dm1"&gt;Stop Mailinator signups with one GET request&lt;/a&gt;. This one adds domain age, SSL and email DNS on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shortest working call
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://domain-trust-score.p.rapidapi.com/checkTrust?domain=stripe.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-host: domain-trust-score.p.rapidapi.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-key: YOUR_RAPIDAPI_KEY'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript (Node 18+):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://domain-trust-score.p.rapidapi.com/checkTrust?domain=stripe.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;domain-trust-score.p.rapidapi.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trustScore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;riskLevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://domain-trust-score.p.rapidapi.com/checkTrust&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain-trust-score.p.rapidapi.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trustScore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;riskLevel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call does DNS, registry and TLS lookups, so expect a second or two. The captures below took 2.1 s and 0.9 s. Set a timeout.&lt;/p&gt;

&lt;h2&gt;
  
  
  The response, field by field
&lt;/h2&gt;

&lt;p&gt;Captured from the live API on 7 Oct 2026 (HTTP 200, 795 bytes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trustScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"riskLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"flags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disposable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disposableMatchedDomain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"freeProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"registeredDomain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stripe.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domainAgeDays"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11348&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"registeredAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1995-09-12T04:00:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"registrar"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SafeNames Ltd."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domainAgeStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domainAgeNote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ssl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"https"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"issuer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DigiCert, Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"validTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-12-10T23:59:59.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"daysRemaining"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hasMx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mxHosts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"aspmx.l.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"alt1.aspmx.l.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"alt2.aspmx.l.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"aspmx2.googlemail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"aspmx3.googlemail.com"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"spf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dmarc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dmarcPolicy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dkimSelectorsFound"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mandrill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dkimWildcardDns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"listsUpdatedAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-05T10:09:51.295Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;trustScore&lt;/code&gt; starts at 100 and loses a fixed penalty per flag, never going below 0. &lt;code&gt;riskLevel&lt;/code&gt; is &lt;code&gt;low&lt;/code&gt; at 75 or more, &lt;code&gt;medium&lt;/code&gt; from 45 to 74, &lt;code&gt;high&lt;/code&gt; below 45.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flags&lt;/code&gt; is the part to read. It lists why the score is what it is. For stripe.com it is empty.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disposable&lt;/code&gt;, &lt;code&gt;disposableMatchedDomain&lt;/code&gt;, &lt;code&gt;freeProvider&lt;/code&gt; come from public disposable-domain lists.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;domainAgeDays&lt;/code&gt;, &lt;code&gt;registeredAt&lt;/code&gt;, &lt;code&gt;registrar&lt;/code&gt; come from the public registry (RDAP). &lt;code&gt;domainAgeStatus&lt;/code&gt; says &lt;code&gt;ok&lt;/code&gt; or why no age is available.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ssl&lt;/code&gt; is a TLS check on port 443 of the domain you sent, including days until expiry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email&lt;/code&gt; is DNS only: MX hosts, SPF, DMARC policy and which of 16 common DKIM selectors exist.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;meta.user&lt;/code&gt; holds the caller's account name, shown as &lt;code&gt;"..."&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A bad one, &lt;code&gt;mailinator.com&lt;/code&gt; (also 7 Oct 2026, 734 bytes), comes back with &lt;code&gt;trustScore: 30&lt;/code&gt;, &lt;code&gt;riskLevel: "high"&lt;/code&gt; and &lt;code&gt;flags: ["disposable_domain"]&lt;/code&gt;. That is 100 minus the 70-point disposable penalty. The other fields (age 8,497 days, valid SSL, SPF and DMARC present) show the score does not mean the domain is new or broken. It means it is a throwaway mail provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  The penalties
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Points&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;disposable_domain&lt;/code&gt;, &lt;code&gt;domain_does_not_exist&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;domain_does_not_resolve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;domain_under_30_days_old&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ssl_invalid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;domain_under_90_days_old&lt;/code&gt;, &lt;code&gt;no_https&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no_mx_records&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;no_spf&lt;/code&gt;, &lt;code&gt;no_dmarc&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;domain_under_1_year_old&lt;/code&gt;, &lt;code&gt;ssl_expires_within_14_days&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dmarc_policy_none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no_dkim_on_common_selectors&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;free_email_provider&lt;/code&gt; and &lt;code&gt;domain_age_unavailable&lt;/code&gt; appear as context and cost nothing. If you disagree with these weights, ignore &lt;code&gt;trustScore&lt;/code&gt; and apply your own rules to &lt;code&gt;flags&lt;/code&gt;, &lt;code&gt;ssl&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;domainAgeDays&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The score is a heuristic from public signals. It is not a guarantee of safety, a certification or a fraud verdict.&lt;/li&gt;
&lt;li&gt;Domain age needs a public RDAP service. In the project's tests of 150 business domains, .ae, .io, .co, .me, .ru and .pk had none, and .au returned no date or was rate-limited. &lt;code&gt;domainAgeStatus&lt;/code&gt; explains this and no penalty applies.&lt;/li&gt;
&lt;li&gt;DKIM cannot be listed from DNS, so 16 common selectors are probed. Finding none does not prove DKIM is absent, which is why the penalty is only 2.&lt;/li&gt;
&lt;li&gt;SSL is checked on the domain you send. A mail-only domain with no website gets &lt;code&gt;no_https&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It does not look at page content, reputation feeds or blocklists.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;th&gt;Body&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Domain read and checked (a domain that does not exist is still 200, with a low score)&lt;/td&gt;
&lt;td&gt;The result above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;domain&lt;/code&gt; missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Pass ?domain=&amp;lt;domain&amp;gt;, for example example.com.","code":400}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;domain&lt;/code&gt; not readable&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Could not read a valid domain from this input.","code":400}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;405&lt;/td&gt;
&lt;td&gt;Any method other than GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Use GET /checkTrust?domain=&amp;lt;domain&amp;gt;.","code":405}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;502&lt;/td&gt;
&lt;td&gt;Unexpected failure inside the API&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Check failed: ...","code":502}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The error bodies are from the API's own documentation and were not re-run on 7 Oct. Gateway failures (bad key, quota used up) return RapidAPI's own error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;The free Basic plan on the listing currently shows 300 requests per month. Pro is $29 per month for 10,000.&lt;/p&gt;

&lt;p&gt;Listing and playground: &lt;a href="https://rapidapi.com/samaanmohammed/api/domain-trust-score" rel="noopener noreferrer"&gt;https://rapidapi.com/samaanmohammed/api/domain-trust-score&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop Mailinator signups with one GET request</title>
      <dc:creator>Mohammed Samaan</dc:creator>
      <pubDate>Wed, 07 Oct 2026 10:08:56 +0000</pubDate>
      <link>https://dev.to/mohammed_samaan_b256ef3f5/stop-mailinator-signups-with-one-get-request-5dm1</link>
      <guid>https://dev.to/mohammed_samaan_b256ef3f5/stop-mailinator-signups-with-one-get-request-5dm1</guid>
      <description>&lt;p&gt;If your free trial lets anyone in with an email address, someone will sign up as &lt;code&gt;x@mailinator.com&lt;/code&gt; forty times. A list lookup at signup is the cheapest first filter. This API does that lookup without you maintaining the lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shortest working call
&lt;/h2&gt;

&lt;p&gt;Subscribe to the free plan on the listing (link at the bottom), copy your key, and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://disposable-email-checker16.p.rapidapi.com/checkDisposable?email=throwaway@mailinator.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-host: disposable-email-checker16.p.rapidapi.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'x-rapidapi-key: YOUR_RAPIDAPI_KEY'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript (Node 18+):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://disposable-email-checker16.p.rapidapi.com/checkDisposable?email=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;throwaway@mailinator.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disposable-email-checker16.p.rapidapi.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disposable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocked:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchedDomain&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://disposable-email-checker16.p.rapidapi.com/checkDisposable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;throwaway@mailinator.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;disposable-email-checker16.p.rapidapi.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-rapidapi-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAPIDAPI_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;disposable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matchedDomain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The response, field by field
&lt;/h2&gt;

&lt;p&gt;Captured from the live API on 7 Oct 2026 (HTTP 200, 322 bytes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"throwaway@mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disposable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"freeProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"matchedLists"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"disposable-email-domains"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"disposable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"mailchecker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"burner-email-providers"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"matchedDomain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mailinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"listsUpdatedAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-05T10:09:51.295Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(&lt;code&gt;meta.user&lt;/code&gt; holds the account name of the caller, shown as &lt;code&gt;"..."&lt;/code&gt; here.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;input&lt;/code&gt; and &lt;code&gt;type&lt;/code&gt;: what you sent, and whether it was read as an &lt;code&gt;email&lt;/code&gt; or a bare &lt;code&gt;domain&lt;/code&gt;. A URL also works; only the domain is used.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;domain&lt;/code&gt;: the domain that was extracted and checked.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disposable&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; if the domain is on at least one list. Subdomains are matched against their parent domain, so you do not need to strip them first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;freeProvider&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; for providers such as Gmail. It is always &lt;code&gt;false&lt;/code&gt; when &lt;code&gt;disposable&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;matchedLists&lt;/code&gt;: which of the five merged public lists flagged the domain. Four of five agree here. A domain flagged by one list is a weaker signal than one flagged by all.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;matchedDomain&lt;/code&gt;: the entry that matched, or &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;listsUpdatedAt&lt;/code&gt;: when the lists were last refreshed. They refresh when older than 7 days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A free provider looks like this (&lt;code&gt;gmail.com&lt;/code&gt;, also captured 7 Oct 2026, 213 bytes): &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;domain&lt;/code&gt;, &lt;code&gt;disposable&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;freeProvider&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;matchedLists&lt;/code&gt; is &lt;code&gt;[]&lt;/code&gt; and &lt;code&gt;matchedDomain&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;. That split lets you reject throwaway domains outright while only flagging free providers on a B2B form.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A domain missing from the lists is not proof the address is real or safe. New throwaway domains appear daily.&lt;/li&gt;
&lt;li&gt;The lists are community-maintained, so false positives happen. Use &lt;code&gt;matchedLists&lt;/code&gt; to see how many agree.&lt;/li&gt;
&lt;li&gt;It never contacts the mailbox. It does not check that the address exists, that the domain has mail servers, or that the user can receive mail. For that you need a confirmation email.&lt;/li&gt;
&lt;li&gt;It is a list lookup. It does not score a domain on age or reputation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Errors
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;th&gt;Body&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Input read and checked&lt;/td&gt;
&lt;td&gt;The result above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;email&lt;/code&gt; missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Pass ?email=&amp;lt;email address or domain&amp;gt;.","code":400}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;email&lt;/code&gt; not readable&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Not a valid email address.","code":400}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;405&lt;/td&gt;
&lt;td&gt;Any method other than GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Use GET /checkDisposable?email=&amp;lt;address or domain&amp;gt;.","code":405}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;502&lt;/td&gt;
&lt;td&gt;Unexpected failure inside the API&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"error":"Check failed: ...","code":502}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 400, 405 and 502 bodies are from the API's own documentation and were not re-run on 7 Oct. Requests that fail at the RapidAPI gateway (a missing or wrong key, or a quota that is used up) return RapidAPI's own error, not this shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;The free Basic plan on the listing currently shows 1,000 requests per month. Paid plans start at $29 per month.&lt;/p&gt;

&lt;p&gt;Listing and playground: &lt;a href="https://rapidapi.com/samaanmohammed/api/disposable-email-checker16" rel="noopener noreferrer"&gt;https://rapidapi.com/samaanmohammed/api/disposable-email-checker16&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
