<?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: Tj Thouhid</title>
    <description>The latest articles on DEV Community by Tj Thouhid (@tjthouhid).</description>
    <link>https://dev.to/tjthouhid</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%2F4189581%2F853516e1-cd3e-46e5-a430-ed6a8995848a.jpg</url>
      <title>DEV Community: Tj Thouhid</title>
      <link>https://dev.to/tjthouhid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tjthouhid"/>
    <language>en</language>
    <item>
      <title>What's using port 3000 on my Mac? Find it, see who started it, and stop it safely</title>
      <dc:creator>Tj Thouhid</dc:creator>
      <pubDate>Sun, 18 Oct 2026 13:07:56 +0000</pubDate>
      <link>https://dev.to/tjthouhid/whats-using-port-3000-on-my-mac-find-it-see-who-started-it-and-stop-it-safely-5h0i</link>
      <guid>https://dev.to/tjthouhid/whats-using-port-3000-on-my-mac-find-it-see-who-started-it-and-stop-it-safely-5h0i</guid>
      <description>&lt;p&gt;You run &lt;code&gt;npm run dev&lt;/code&gt; and get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: listen EADDRINUSE: address already in use :::3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The usual advice is "find the PID and kill it". That works, but it skips the questions that actually matter. &lt;em&gt;What&lt;/em&gt; is on port 3000? Which project does it belong to? Did I start it, did my editor, or did an AI agent start it in the background an hour ago? And is it safe to stop?&lt;/p&gt;

&lt;p&gt;Here's how to answer all of that on macOS with commands that are already installed. After that, I'll show how I do the same thing in a Mac app I build.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A quick look
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; :3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On macOS, plain &lt;code&gt;lsof -i :3000&lt;/code&gt; may print a service name such as &lt;code&gt;hbci&lt;/code&gt; instead of &lt;code&gt;3000&lt;/code&gt;; step 2 fixes that.&lt;/p&gt;

&lt;p&gt;This lists every process with a network connection on port 3000. That includes the server, but also your browser tabs that are connected to it, so the list can be longer than you expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Just the thing that's listening
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsof &lt;span class="nt"&gt;-nP&lt;/span&gt; &lt;span class="nt"&gt;-iTCP&lt;/span&gt;:3000 &lt;span class="nt"&gt;-sTCP&lt;/span&gt;:LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-iTCP:3000&lt;/code&gt; limits it to TCP on port 3000.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-sTCP:LISTEN&lt;/code&gt; shows only the process that's &lt;em&gt;listening&lt;/em&gt;, which is the one holding the port.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-n&lt;/code&gt; and &lt;code&gt;-P&lt;/code&gt; skip name lookups. It's faster, and you see &lt;code&gt;3000&lt;/code&gt; rather than a service name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll get something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node    48213 tj     23u  IPv6  0x...       0t0  TCP *:3000 (LISTEN)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might see two lines, one for IPv4 and one for IPv6. They can even be two different processes. That's how you get the confusing case where the browser shows an old version of your app while your terminal says the new one started fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. What is it, who owns it, and for how long?
&lt;/h2&gt;

&lt;p&gt;Take the PID and ask &lt;code&gt;ps&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps &lt;span class="nt"&gt;-p&lt;/span&gt; 48213 &lt;span class="nt"&gt;-o&lt;/span&gt; pid,ppid,user,etime,command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  PID  PPID USER  ELAPSED COMMAND
48213 48190 tj   01:12:40 node /Users/tj/code/shop/node_modules/.bin/vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;command&lt;/strong&gt; is the full command line. It often includes the project path (&lt;code&gt;/Users/tj/code/shop&lt;/code&gt; here), which is usually the quickest way to tell which project it belongs to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;etime&lt;/strong&gt; (shown as ELAPSED) is how long it's been running. An hour and twelve minutes means this isn't the server you just tried to start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;user&lt;/strong&gt; is who owns it. If it isn't you, see step 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ppid&lt;/strong&gt; is the parent process. Run the same command on it to see what launched it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps &lt;span class="nt"&gt;-p&lt;/span&gt; 48190 &lt;span class="nt"&gt;-o&lt;/span&gt; pid,ppid,user,etime,command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep going up and you'll usually hit &lt;code&gt;zsh&lt;/code&gt; and then Terminal, an editor's helper process (VS Code, for example), or an AI tool's shell. If the PPID is &lt;code&gt;1&lt;/code&gt;, the original parent has exited and macOS's &lt;code&gt;launchd&lt;/code&gt; adopted the process. That's typical for a server left running in the background after the thing that started it went away.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Nothing shows up? It may belong to another user
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lsof&lt;/code&gt; only lists your own processes unless you run it with &lt;code&gt;sudo&lt;/code&gt;:&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="nb"&gt;sudo &lt;/span&gt;lsof &lt;span class="nt"&gt;-nP&lt;/span&gt; &lt;span class="nt"&gt;-iTCP&lt;/span&gt;:3000 &lt;span class="nt"&gt;-sTCP&lt;/span&gt;:LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the port is held by a process owned by &lt;code&gt;root&lt;/code&gt; or another user, this is how you'll see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Stop it, gently first
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;kill &lt;/span&gt;48213
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kill&lt;/code&gt; sends a polite "please quit" signal (SIGTERM), so the program can shut down properly. Give it a couple of seconds and run the &lt;code&gt;lsof&lt;/code&gt; command from step 2 again. Only if it's still there:&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="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; 48213
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kill -9&lt;/code&gt; ends it immediately, with no chance to clean up. Use it as the second step, not the first.&lt;/p&gt;

&lt;p&gt;A few things to watch for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Another user's process.&lt;/strong&gt; You'll get "Operation not permitted". You'd need &lt;code&gt;sudo kill 48213&lt;/code&gt;, so first be sure it's really something you mean to stop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Still busy after you stopped it?&lt;/strong&gt; Dev servers often start child processes. Run step 2 again and see what's listening now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It comes straight back?&lt;/strong&gt; Something is restarting it, such as a service manager, Docker, or an app like Laravel Herd. Stop it there instead of killing it again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ports 5000 and 7000.&lt;/strong&gt; On recent macOS versions, AirPlay Receiver listens on these. If a Flask app can't get port 5000, that's probably why. Pick another port, or turn AirPlay Receiver off in System Settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The same thing in Lokstack
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I build Lokstack, and this part is about my own app.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I built Lokstack partly because I got tired of running these commands one after another. It's a free Mac app, and everything in this section is on the free plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ports page.&lt;/strong&gt; Search for &lt;code&gt;3000&lt;/code&gt;. Lokstack shows which program holds the port, which project it belongs to, who started it, and how long it's been up. There are two buttons. &lt;strong&gt;Stop&lt;/strong&gt; asks the program to quit, like &lt;code&gt;kill&lt;/code&gt;. &lt;strong&gt;Kill&lt;/strong&gt; is the force option, like &lt;code&gt;kill -9&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb73k57tmk1xi1ddybtck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb73k57tmk1xi1ddybtck.png" alt="Lokstack Ports page: a listening port with the program, project, who started it, uptime, and Stop and Kill buttons" width="799" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Why won't it start?" on a project's Overview.&lt;/strong&gt; If the project has a saved port and something else is using it, a red box says &lt;strong&gt;"Port 3000 is already taken"&lt;/strong&gt; with a &lt;strong&gt;Free port 3000&lt;/strong&gt; button. That's the one-click version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run &amp;amp; logs.&lt;/strong&gt; If the app you start prints &lt;code&gt;EADDRINUSE&lt;/code&gt; or "address already in use", Lokstack explains it in plain words and offers the same fix.&lt;/p&gt;

&lt;p&gt;What it won't do, so you know where the edges are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Databases and services are protected.&lt;/strong&gt; Lokstack won't stop them by accident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programs owned by another user&lt;/strong&gt; (for example a server running as root) can't be stopped from Lokstack. It says "Permission denied", and in Terminal you'd need &lt;code&gt;sudo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laravel Herd sites&lt;/strong&gt; are stopped by asking Herd to stop all its services, not by killing that one process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Free port button only appears for projects with a saved port.&lt;/strong&gt; Stop and Kill on the Ports page always work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;When you see &lt;code&gt;EADDRINUSE&lt;/code&gt;, find out what's actually listening, check what it is and who owns it, and stop it gently before you force it. If it keeps coming back, stop it where it's managed (Docker, a service manager, Herd) instead.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Lokstack is a free Mac app that shows what is using a port, which project it belongs to and who started it, and lets you stop it in one click. It won't touch your databases by accident. If you'd rather stay in Terminal, the commands above are all you need. &lt;a href="https://lokstack.app" rel="noopener noreferrer"&gt;https://lokstack.app&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's the strangest thing you've found holding a port? I'd like to hear it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>macos</category>
      <category>webdev</category>
      <category>node</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
