<?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: Yuanming Xiao</title>
    <description>The latest articles on DEV Community by Yuanming Xiao (@yuanming_xiao).</description>
    <link>https://dev.to/yuanming_xiao</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%2F4231402%2Fb4db5a16-0994-4b79-9994-04f9232582da.png</url>
      <title>DEV Community: Yuanming Xiao</title>
      <link>https://dev.to/yuanming_xiao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yuanming_xiao"/>
    <language>en</language>
    <item>
      <title>How to tell whether an online tool uploads your file, in about 20 seconds</title>
      <dc:creator>Yuanming Xiao</dc:creator>
      <pubDate>Sat, 07 Nov 2026 03:30:24 +0000</pubDate>
      <link>https://dev.to/yuanming_xiao/how-to-tell-whether-an-online-tool-uploads-your-file-in-about-20-seconds-3co7</link>
      <guid>https://dev.to/yuanming_xiao/how-to-tell-whether-an-online-tool-uploads-your-file-in-about-20-seconds-3co7</guid>
      <description>&lt;h1&gt;
  
  
  How to tell whether an online tool uploads your file, in about 20 seconds
&lt;/h1&gt;

&lt;p&gt;Every web tool says it is private. Almost none of them let you check. The good news is you do not need permission — you need the Network tab.&lt;/p&gt;

&lt;p&gt;I paste customer data, private keys and production JSON into browser tools fairly often, so I stopped taking the claim on trust and started testing it. Here is the check, and what the results actually mean.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 20-second version: go offline
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the tool. Let the page finish loading.&lt;/li&gt;
&lt;li&gt;Open DevTools (F12) → &lt;strong&gt;Network&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Set the throttling dropdown to &lt;strong&gt;Offline&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use the tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A tool that runs locally keeps working. A tool that uploads breaks immediately, usually with a failed fetch or a spinner that never resolves.&lt;/p&gt;

&lt;p&gt;This single test is the fastest lie detector I know, and it works because it tests the property you actually care about: whether your input can leave the machine at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The precise version: read the payload
&lt;/h2&gt;

&lt;p&gt;Offline mode can produce false negatives — a tool might work offline for the demo but upload on "Convert". So for anything sensitive, do it the slow way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DevTools → Network → filter to &lt;strong&gt;Fetch/XHR&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Press the clear button.&lt;/li&gt;
&lt;li&gt;Now paste your input and run the tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then look at what appeared.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local processing&lt;/strong&gt; produces a short list that has nothing to do with your input: the analytics beacon, maybe a font, maybe a config JSON. Request counts vary. What matters is payload size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An upload&lt;/strong&gt; shows up as a &lt;code&gt;POST&lt;/code&gt; — commonly to a path named &lt;code&gt;/upload&lt;/code&gt;, &lt;code&gt;/convert&lt;/code&gt;, &lt;code&gt;/api/v1/files&lt;/code&gt; or similar — with a request body roughly the size of what you pasted. Click it and check two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request headers&lt;/strong&gt;: &lt;code&gt;Content-Type: multipart/form-data; boundary=...&lt;/code&gt; for a file, or &lt;code&gt;application/json&lt;/code&gt; with your text inside, is conclusive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload / Request tab&lt;/strong&gt;: if your data is visible there, it left your browser. No privacy policy changes that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One caveat worth knowing: WebAssembly and Web Workers do real work without making requests, so the &lt;strong&gt;absence&lt;/strong&gt; of network traffic is strong evidence of local processing, while the &lt;strong&gt;presence&lt;/strong&gt; of a few requests is not evidence of an upload. Judge by what is in the request, not by how many requests there are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things that legitimately leave the tab
&lt;/h2&gt;

&lt;p&gt;It helps to know what normal looks like, so you do not mistake it for a leak:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Page weight.&lt;/strong&gt; HTML, CSS, fonts, the analytics ping. None of it contains your input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliberate API calls.&lt;/strong&gt; A tool that calls a translation service is uploading by another name, even if it calls it "processing". The Network tab tells you which one you are using.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser-provided features.&lt;/strong&gt; Text-to-speech via the Web Speech API uses voices installed on the operating system. That is local, and it looks different from a call to a cloud TTS endpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why "we do not store it" is a different promise
&lt;/h2&gt;

&lt;p&gt;These are three separate claims and only the first one is checkable from your side:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Claim&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;th&gt;Verifiable by you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Nothing is uploaded"&lt;/td&gt;
&lt;td&gt;Your input never leaves the device&lt;/td&gt;
&lt;td&gt;Yes — Network tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"We do not store it"&lt;/td&gt;
&lt;td&gt;It arrived, but is deleted&lt;/td&gt;
&lt;td&gt;Only by them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"We delete it after an hour"&lt;/td&gt;
&lt;td&gt;It arrived and sat somewhere&lt;/td&gt;
&lt;td&gt;Only by them&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first row is the only one where you can stop trusting and start testing. When someone offers you the third row, ask why they need the first hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this actually costs you
&lt;/h2&gt;

&lt;p&gt;The failure is rarely dramatic. It looks like a small convenience: paste a &lt;code&gt;.env&lt;/code&gt; to check a syntax error, drop a customer CSV into a converter, decode a token that happens to contain a live key. Files under a megabyte feel disposable, and that feeling is exactly what makes the habit stick.&lt;/p&gt;

&lt;p&gt;The size of the file is not the thing. The thing is whether it left the machine.&lt;/p&gt;

&lt;p&gt;Two examples of the check applied to tools you can try it on right now: a &lt;a href="https://itoolnet.com/format/json-format" rel="noopener noreferrer"&gt;JSON formatter&lt;/a&gt; and a &lt;a href="https://itoolnet.com/encoding/base64-decode" rel="noopener noreferrer"&gt;Base64 decoder&lt;/a&gt;. Both keep working with the network tab set to Offline, which is the only claim either of them makes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I maintain itoolnet, the site linked above. The offline test in this post is what I use on my own pages before shipping them, and it has caught two regressions so far — which is the actual argument for running it on anyone's tool, including mine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>productivity</category>
      <category>security</category>
      <category>tools</category>
    </item>
  </channel>
</rss>
