UDP Portscanning in PHP

Share this article

Portscanning serves a legitimate role in system administration/ownership. By confirming exactly what ports a computer accepts connections on, it’s possible to ensure that an operating system hasn’t opened unnecessary ports to the world at large as part of a default install. It also allows us to check that our system hasn’t been compromised and had ports opened to allow a cracker to send remote commands to our machine via the Internet.

While TCP port scanning of one’s own ports is common, many underestimate the potential hazards of open UDP ports — this can lead to compromise, or indicate that a compromise has occurred. As the nmap manpage says:

“There is also the cDc Back Orifice backdoor program which hides on a configurable UDP port on Windows machines. Not to mention the many commonly vulnerable services that utilize UDP such as snmp, tftp, NFS, etc.”

The single largest impediment to the average home user conducting port scans of their own machines is the lack of simple software to conduct the scan for them. Don’t get me wrong — nmap is one of the best portscanning tools available — but how comfortable is Joe Average User going to be using a *nix command line tool? It seems to me that a tool that only requires Mr. Average User to go to a specific URL and wait while a PHP script runs a TCP and UDP scan against their machine, and then returns the results of the scan to them, is just what the doctor ordered.

With this in mind, I started searching the Internet and found an implementation of a TCP port scanner that Jim Barcelona had coded and made available at php wizard

Great! With half of the work done, I should be able to whip out a UDP port scanner in no time. I mean, how much harder could coding a UDP port scanner be? Considerably harder, as it turns out.

TCP Portscanning in PHP

When a TCP socket is created using the fsockopen function, you specify the IP address of the remote machine and the port number to which you want to connect. Using the underlying socket functionality, PHP will then attempt to create a virtual circuit to the remote machine on the specified port, in order to allow further communication to occur. If the destination port is unavailable, then the TCP provider on the remote machine will reject the connection request and the fsockopen function will be return a boolean value of failed.

So we now have an easy to understand and implement TCP portscanner. We set up a loop that specifies the minimum and maximum port numbers that we wish to scan, and within the loop, attempt to open a connection at the current value of the loop’s index. If the attempt to open the port fails, there’s no service at that port. If we’re able to successfully open a socket to that port, then there’s a service at that port which we log in our array of open ports as a key. We then insert the value for that key with a call to getservbyport, which will return the unix service that’s normally registered at that port. Lastly, we close the open socket and move onto the next iteration of our loop.

UDP Portscanning in PHP

When an application wishes to send data over the network using the UDP protocol, it gives the data to UDP through the assigned port number, also telling UDP which port on the destination system the data should be sent to. UDP then creates a UDP message, marking the source and destination port numbers, which is then passed off to IP for delivery.

When a UDP packet is received by the destination machine, the UDP software looks at the packet’s header for the destination port number, and hands the payload off to whatever application has registered as using that port number. If no application has registered for the specified port number, then an “ICMP Destination Unreachable: Port Unreachable” Error Message is returned to the remote machine, and the payload is discarded.

Creating a UDP socket in PHP is similar to creating a TCP socket, with a couple of differences. You still call the fsockopen function, but you must specify:

  • that you want to use the UDP protocol,
  • the IP address of the remote computer and
  • the port number that you want to connect with.

In contrast to the TCP socket, at this point no connection exists to the remote computer.

function _scanPort ($portNumber) {  
$handle = fsockopen($this-> targetIP, $portNumber, &$errno, &$errstr, 2);  
 
if (!$handle) {  
echo "$errno : $errstr <br/>";  
}  
 
socket_set_timeout ($handle, $this-> timeout);  
$write = fwrite($handle,"x00");  
if (!$write) {  
echo "error writing to port: $index.<br/>";  
next;  
}  
 
$startTime = time();  
$header = fread($handle, 1);  
$endTime = time();  
$timeDiff = $endTime - $startTime;  
 
if ($timeDiff >= $this-> timeout) {  
fclose($handle);  
return 1;  
} else {  
fclose($handle);  
return 0;  
}  
}

Because a call to read from our UDP socket will block (wait until it receives data), we set a value to the set_socket_timeout function. This tells the socket to only listen (block) on the socket for a response from the remote machine for a specific period of time. If that time is exceeded, then the socket will stop listening, and the code will continue to run. We’ll see how we use this to discern an open port shortly.

As UDP is connectionless, at this point a virtual circuit is not setup with the remote machine. Instead, you have to pass the data that you want to send to the remote machine through the socket using the fwrite function. We then immediately log the time that we begin listening for a response from the remote machine, and use fread to listen to the socket. At this point, one of two things can happen:

  1. the remote server returns an “ICMP Destination Unreachable: Port Unreachable” Error Message to us, and the fread ends, or

  2. the socket times out waiting for a response.

In either case, we now log the time that the listening ended, and derive the total time spent listening by subtracting the end time from the start time. We compare this number with the socket’s timeout value that we set. If it’s less than the timeout value, then the remote server returned an “ICMP Destination Unreachable: Port Unreachable” Error Message to us, and we know that the port is closed. If the socket timed out, then we know one of two other things occurred: the application at that port was waiting to receive a valid command, or the packet was lost in transit (UDP doesn’t offer guaranteed delivery, and if a packet is lost en route, we’re not going to receive any information to that effect).

So, we’ve established a means to discern whether there’s anything at the port (ie. the socket returned before it timed out), and we now need a way to tell whether a socket timing out was the result of an application waiting for legitimate data, or the packet was lost in transit. The easiest way to do this would be to send multiple packets to that port, and if we get one response back that doesn’t timeout, then we know that there’s not an application there and the port is closed. But how can we do this in a manner that’s not too wasteful of bandwidth, and minimizes the application’s run time?

Prior to our full scan of the UDP ports that the class was instructed to scan, we’re going to conduct a smaller port scan very high in the port range, to minimize the finding of legitimate open ports, and test the network conditions between the machines. This initial scan is carried out in our _networkProbe method. Since most of the open UDP ports that are open are at or below port 1024, we’ll do a scan up in the port 55000 range. Any ports that time out this high in the port range we can assume did so because of lost datagrams, and not because we’ve detected an open port.

function _networkProbe ($noTrials=100, $startPortNumber=55000) {   
$endPortNumber = $startPortNumber + $noTrials;  
 
// temporarily set timeout to 2 seconds. we'll modify this with the  
// data that we get from this method  
 
$this-> timeout = 2;  
 
// setup a for loop to scan the ports  
 
for ($portNumber = $startPortNumber; $portNumber < $endPortNumber;  
 $portNumber++) {  
$startTime = $this-> _getmicrotime();  
$result = $this-> _scanPort($portNumber);  
$endTime = $this-> _getmicrotime();  
$timeDiff = $endTime - $startTime;  
 
if (!$result) {  
$responsesArray[] = $timeDiff;  
$totalTime += $timeDiff;  
}  
}  
 
$noResponses = count($responsesArray);  
 
// if more than 40% of the datagrams timed out, abort the scan  
 
if ($noResponses < (.6 * $noTrial)) {  
echo "The connection is losing too many packets. Scan aborted. <br/>";  
exit;  
}  
 
$averageResponseTime = $this-> _calcAvgResponseTime ($noResponses,  
 $totalTime);  
$standardDeviation = $this-> _calcStdrDeviation ($responsesArray);  
 
 // calculate the timeout value  
 
$timeoutValue = ceil($averageResponseTime + 4 * $standardDeviation);  
 
// calculate number of cleanup iterations we'll need  
// percentFalsePositive is the % of datagrams that we sent in  
// the trial that timed out  
 
$percentFalsePositives = ($noTrials - $noResponses)/$noTrials;  
 
// percentResponses is the % of datagrams that we sent in the trial  
// that returned (eg -- didn't timeout)  
 
$percentResponses = $noResponses/$noTrials;  
 
// calculate the total number of ports to be scanned in the  
// real scan  
 
$portRange = $this-> maxPort - $this-> minPort + 1;  
 
// estFalsePositives is the estimated number of false positives we  
// anticipate getting from the real scan  
 
$estFalsePositives = $portRange * $percentFalsePositives;  
 
$this-> cleanupIterations = $this->  
_calcNoIterations ($estFalsePositives, $percentResponses, $portRange);  
 
if ($this-> debug == 1) {  
echo "<br/>";  
echo "total time $totalTime<br/>";  
echo "timeout value: " . $this-> timeout . "<br/>";  
echo "cleanup iterations: " . $this-> cleanupIterations . "<br/>";  
echo "<br/>";  
flush();  
}  
}

So we now know:

  • the number of packets that were lost from our sample,
  • the total number of packets that were sent and
  • the average time that it we had to listen for each packet that did respond without blocking.

With the number of packets lost from our sample, the total packets sent with our initial scan, and the range of how many ports we’re going to scan in the main scan, we can calculate the number of iterations that we’ll have to run, and retest the open ports detected, to eliminate false positives. The formula that we use to do this is an exponential decay logarithm and it’s functionallity can be found in the _calcNoIterations method of the class.

We’re also going to use the average response time of the fread calls that returned an “ICMP Destination Unreachable: Port Unreachable” Error Message and didn’t block, to calculate the standard deviation of these individual times. We multiply the standard deviation by a factor of four (four sigma) and add it to our average response time. This allows us to minimize the timeout value, and still be reasonably certain that we’re not eliminating too many scans that would’ve returned had it not timed out. At this point, this check is actually superfluous given that the set_socket_timeout value can’t be set to a value of less than one second, which is where most of the derived timeout values are going to be. However, if the socket timeout value is ever modified to accept values of less than one second, we can anticipate a runtime decrease up to a factor of five in eliminating the ports that don’t have a service on them.

Using the UDP Portscanning Class

The UDP Port Scanning Class does an excellent job of abstracting the complexities of UDP port scanning. Use of the class is simplicity itself: include the class and new up an object based on the class that’s passing it the the target ip address, and optionally, the port to start scanning at, the port to end scanning at, and whether the object should output information as it conducts the scan. By default, the start port is set to 1, the end port is set to 1024, and output is on.

Then call the objects doScan method and assign its output to a variable that will hold the results of the scan as an array. Here’s an example:

include ('classes/udpPortScanner.inc');   
 
$udpScanner = new udpPortScanner("$REMOTE_ADDR");  
$ports = $udpScanner-> doScan();  
 
if (count($ports) == 0) {  
echo "no open udp ports detected.<br/>";  
} else {  
echo "open udp ports:<br/>";  
foreach ($ports as $portNumber => $service) {  
echo "$portNumber ($service)<br/>";  
}  
}

Closing

There are two modifications that I have to make and another that I’d like to make. First, the calculated value of the number of iterations to eliminate false positives resulted in a number that is too low if the network conditions are good, and I was getting ports returned that were not, in fact, open. I modified the code to bump the minimum number of cleanup iterations up to a value of five in order to compensate for this.

A UDP port scanner is heavily reliant upon the network conditions that exist between the two machines. In testing, I had friends in both Australia and South Africa (I’m located in the U.S.) volunteer to be scanned, and the scanner was having a really difficult time detecting closed ports. This was because the network conditions were leading to a very large number of packets being lost in transit, and very long runtimes were encountered. In defense of the scanner, an nmap scan of the first 1024 UDP ports on the host in South Africa took nearly an hour, indicating that this is endemic to UDP port scanning, not to this scanner’s implementation. With this in mind, it became obvious that some of the network connections were just too bad to complete a scan in a reasonable amount of time. Because of this, I modified the code to abort if, during the initial network testing scan, more than 40% of the packets were lost. Feel free to eliminate or modify this value, but be warned that scanning over a bad network span can take a considerable amount of time.

Finally, I’d also like to collect information as to what ports Microsoft places its various services on, to complement the getservbyport function, which will only return services that are mapped to the traditional ports on a *nix box. I could then specify which Microsoft service is running on a port, and in a later version, indicate how comprimising this is, and describe methods to disable the service and close the port if it’s not in use.

I’d like to thank David LaCroix of suddendecelaration.com for his assistance in setting up tcpdump for me to analyze the UDP port scans that I was conducting against one of his volunteered machines. His assistance was instrumental in completing the debugging of this software. Also, thanks to Daniel Bogan of waferbaby.com and Zak McGregor of carfolio.com, both of whom were helpful in determining that trans-oceanic UDP port scans are not that great an idea.

For additional information on Internet protocols, I highly recommend O’Reilly and Associates “Internet Core Protocols: The Definitive Guide,” by Erik A. Hall. You can find more information on O’Reilly’s Website.

The official home for the the tcpPortScan and udpPortScan classes is here. You can check there for the latest updates to the classes and to report any problems, issues or suggestions that you have.

Frequently Asked Questions about UDP Port Scanning in PHP

What is UDP port scanning and why is it important in PHP?

UDP, or User Datagram Protocol, is one of the core protocols in the Internet protocol suite. UDP port scanning is a process that sends client requests to server port addresses to identify online services. In PHP, UDP port scanning is important as it allows developers to identify open ports and services available on a host network. This can be useful in network security to identify potential vulnerabilities.

How does UDP port scanning differ from TCP port scanning?

While both UDP and TCP port scanning are used to identify open ports and services on a network, they operate differently. TCP, or Transmission Control Protocol, is a connection-oriented protocol, meaning it requires a connection to be established before data can be sent. UDP, on the other hand, is a connectionless protocol. It doesn’t require a connection to send data, making it faster but less reliable than TCP.

How can I implement UDP port scanning in PHP?

Implementing UDP port scanning in PHP involves creating a socket, setting socket options, and then using the socket to send and receive data. PHP has built-in functions for this, such as socket_create(), socket_set_option(), and socket_sendto(). You can find detailed examples and explanations in the article.

What are some common issues I might encounter when performing UDP port scanning in PHP?

Some common issues include firewall restrictions, which can block UDP packets, and PHP configuration settings, which may limit the execution time of scripts. Additionally, because UDP is a connectionless protocol, it can be difficult to determine whether a port is open or closed.

How can I troubleshoot issues with UDP port scanning in PHP?

Troubleshooting UDP port scanning in PHP often involves checking the error codes returned by the socket functions. PHP provides the socket_strerror() function, which returns a string describing the error. Additionally, you may need to adjust PHP configuration settings or firewall rules.

Can I use UDP port scanning to test the security of my network?

Yes, UDP port scanning can be a useful tool in network security. By identifying open ports and services, you can identify potential vulnerabilities and take steps to secure them.

Are there any libraries or tools that can simplify UDP port scanning in PHP?

While PHP has built-in functions for socket programming, there are also libraries and tools that can simplify the process. For example, the PHP Socket Class provides an object-oriented interface for socket programming.

How can I optimize the performance of my UDP port scanning script in PHP?

Performance optimization can involve a variety of strategies, such as using non-blocking sockets, adjusting the timeout value, or using multithreading to scan multiple ports simultaneously.

What are some best practices for UDP port scanning in PHP?

Best practices include handling errors properly, using non-blocking sockets to improve performance, and being mindful of the potential impact on network resources. Additionally, it’s important to respect the privacy and security of others when performing port scanning.

Can I use UDP port scanning in PHP to send data to an IP address?

Yes, you can use UDP port scanning in PHP to send data to an IP address. This involves creating a socket, setting socket options, and then using the socket_sendto() function to send data to the specified IP address and port.

Jason PerkinsJason Perkins
View Author

Jason's been involved with Web development since 1996 and currently resides in Chicago, IL. Visit his personal site at www.somebodydial911.com.

Share this article
Read Next
Retrieval-augmented Generation: Revolution or Overpromise?
Retrieval-augmented Generation: Revolution or Overpromise?
Kateryna ReshetiloOlexandr Moklyak
How to Deploy Apache Airflow on Vultr Using Anaconda
How to Deploy Apache Airflow on Vultr Using Anaconda
Vultr
Cloud Native: How Ampere Is Improving Nightly Arm64 Builds
Cloud Native: How Ampere Is Improving Nightly Arm64 Builds
Dave NearyAaron Williams
How to Create Content in WordPress with AI
How to Create Content in WordPress with AI
Çağdaş Dağ
A Beginner’s Guide to Setting Up a Project in Laravel
A Beginner’s Guide to Setting Up a Project in Laravel
Claudio Ribeiro
Enhancing DevSecOps Workflows with Generative AI: A Comprehensive Guide
Enhancing DevSecOps Workflows with Generative AI: A Comprehensive Guide
Gitlab
Creating Fluid Typography with the CSS clamp() Function
Creating Fluid Typography with the CSS clamp() Function
Daine Mawer
Comparing Full Stack and Headless CMS Platforms
Comparing Full Stack and Headless CMS Platforms
Vultr
7 Easy Ways to Make a Magento 2 Website Faster
7 Easy Ways to Make a Magento 2 Website Faster
Konstantin Gerasimov
Powerful React Form Builders to Consider in 2024
Powerful React Form Builders to Consider in 2024
Femi Akinyemi
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Ralph Mason
Sending Email Using Node.js
Sending Email Using Node.js
Craig Buckler
Creating a Navbar in React
Creating a Navbar in React
Vidura Senevirathne
A Complete Guide to CSS Logical Properties, with Cheat Sheet
A Complete Guide to CSS Logical Properties, with Cheat Sheet
Ralph Mason
Using JSON Web Tokens with Node.js
Using JSON Web Tokens with Node.js
Lakindu Hewawasam
How to Build a Simple Web Server with Node.js
How to Build a Simple Web Server with Node.js
Chameera Dulanga
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Beloslava Petrova
Crafting Interactive Scatter Plots with Plotly
Crafting Interactive Scatter Plots with Plotly
Binara Prabhanga
GenAI: How to Reduce Cost with Prompt Compression Techniques
GenAI: How to Reduce Cost with Prompt Compression Techniques
Suvoraj Biswas
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
Aurelio De RosaMaria Antonietta Perna
Quick Tip: How to Align Column Rows with CSS Subgrid
Quick Tip: How to Align Column Rows with CSS Subgrid
Ralph Mason
15 Top Web Design Tools & Resources To Try in 2024
15 Top Web Design Tools & Resources To Try in 2024
SitePoint Sponsors
7 Simple Rules for Better Data Visualization
7 Simple Rules for Better Data Visualization
Mariia Merkulova
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
SitePoint Team
Best Programming Language for AI
Best Programming Language for AI
Lucero del Alba
Quick Tip: How to Add Gradient Effects and Patterns to Text
Quick Tip: How to Add Gradient Effects and Patterns to Text
Ralph Mason
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Vultr
How to Optimize Website Content for Featured Snippets
How to Optimize Website Content for Featured Snippets
Dipen Visavadiya
Psychology and UX: Decoding the Science Behind User Clicks
Psychology and UX: Decoding the Science Behind User Clicks
Tanya Kumari
Build a Full-stack App with Node.js and htmx
Build a Full-stack App with Node.js and htmx
James Hibbard
Digital Transformation with AI: The Benefits and Challenges
Digital Transformation with AI: The Benefits and Challenges
Priyanka Prajapat
Quick Tip: Creating a Date Picker in React
Quick Tip: Creating a Date Picker in React
Dianne Pena
How to Create Interactive Animations Using React Spring
How to Create Interactive Animations Using React Spring
Yemi Ojedapo
10 Reasons to Love Google Docs
10 Reasons to Love Google Docs
Joshua KrausZain Zaidi
How to Use Magento 2 for International Ecommerce Success
How to Use Magento 2 for International Ecommerce Success
Mitul Patel
5 Exciting New JavaScript Features in 2024
5 Exciting New JavaScript Features in 2024
Olivia GibsonDarren Jones
Tools and Strategies for Efficient Web Project Management
Tools and Strategies for Efficient Web Project Management
Juliet Ofoegbu
Choosing the Best WordPress CRM Plugin for Your Business
Choosing the Best WordPress CRM Plugin for Your Business
Neve Wilkinson
ChatGPT Plugins for Marketing Success
ChatGPT Plugins for Marketing Success
Neil Jordan
Managing Static Files in Django: A Comprehensive Guide
Managing Static Files in Django: A Comprehensive Guide
Kabaki Antony
The Ultimate Guide to Choosing the Best React Website Builder
The Ultimate Guide to Choosing the Best React Website Builder
Dianne Pena
Exploring the Creative Power of CSS Filters and Blending
Exploring the Creative Power of CSS Filters and Blending
Joan Ayebola
How to Use WebSockets in Node.js to Create Real-time Apps
How to Use WebSockets in Node.js to Create Real-time Apps
Craig Buckler
Best Node.js Framework Choices for Modern App Development
Best Node.js Framework Choices for Modern App Development
Dianne Pena
SaaS Boilerplates: What They Are, And 10 of the Best
SaaS Boilerplates: What They Are, And 10 of the Best
Zain Zaidi
Understanding Cookies and Sessions in React
Understanding Cookies and Sessions in React
Blessing Ene Anyebe
Enhanced Internationalization (i18n) in Next.js 14
Enhanced Internationalization (i18n) in Next.js 14
Emmanuel Onyeyaforo
Essential React Native Performance Tips and Tricks
Essential React Native Performance Tips and Tricks
Shaik Mukthahar
How to Use Server-sent Events in Node.js
How to Use Server-sent Events in Node.js
Craig Buckler
Five Simple Ways to Boost a WooCommerce Site’s Performance
Five Simple Ways to Boost a WooCommerce Site’s Performance
Palash Ghosh
Elevate Your Online Store with Top WooCommerce Plugins
Elevate Your Online Store with Top WooCommerce Plugins
Dianne Pena
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Dianne Pena
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
Vultr
Enhance Your React Apps with ShadCn Utilities and Components
Enhance Your React Apps with ShadCn Utilities and Components
David Jaja
10 Best Create React App Alternatives for Different Use Cases
10 Best Create React App Alternatives for Different Use Cases
Zain Zaidi
Control Lazy Load, Infinite Scroll and Animations in React
Control Lazy Load, Infinite Scroll and Animations in React
Blessing Ene Anyebe
Building a Research Assistant Tool with AI and JavaScript
Building a Research Assistant Tool with AI and JavaScript
Mahmud Adeleye
Understanding React useEffect
Understanding React useEffect
Dianne Pena
Web Design Trends to Watch in 2024
Web Design Trends to Watch in 2024
Juliet Ofoegbu
Building a 3D Card Flip Animation with CSS Houdini
Building a 3D Card Flip Animation with CSS Houdini
Fred Zugs
How to Use ChatGPT in an Unavailable Country
How to Use ChatGPT in an Unavailable Country
Dianne Pena
An Introduction to Node.js Multithreading
An Introduction to Node.js Multithreading
Craig Buckler
How to Boost WordPress Security and Protect Your SEO Ranking
How to Boost WordPress Security and Protect Your SEO Ranking
Jaya Iyer
Understanding How ChatGPT Maintains Context
Understanding How ChatGPT Maintains Context
Dianne Pena
Building Interactive Data Visualizations with D3.js and React
Building Interactive Data Visualizations with D3.js and React
Oluwabusayo Jacobs
JavaScript vs Python: Which One Should You Learn First?
JavaScript vs Python: Which One Should You Learn First?
Olivia GibsonDarren Jones
13 Best Books, Courses and Communities for Learning React
13 Best Books, Courses and Communities for Learning React
Zain Zaidi
5 jQuery.each() Function Examples
5 jQuery.each() Function Examples
Florian RapplJames Hibbard
Implementing User Authentication in React Apps with Appwrite
Implementing User Authentication in React Apps with Appwrite
Yemi Ojedapo
AI-Powered Search Engine With Milvus Vector Database on Vultr
AI-Powered Search Engine With Milvus Vector Database on Vultr
Vultr
Understanding Signals in Django
Understanding Signals in Django
Kabaki Antony
Why React Icons May Be the Only Icon Library You Need
Why React Icons May Be the Only Icon Library You Need
Zain Zaidi
View Transitions in Astro
View Transitions in Astro
Tamas Piros
Getting Started with Content Collections in Astro
Getting Started with Content Collections in Astro
Tamas Piros
What Does the Java Virtual Machine Do All Day?
What Does the Java Virtual Machine Do All Day?
Peter Kessler
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Mayank Singh
Layouts in Astro
Layouts in Astro
Tamas Piros
.NET 8: Blazor Render Modes Explained
.NET 8: Blazor Render Modes Explained
Peter De Tender
Mastering Node CSV
Mastering Node CSV
Dianne Pena
A Beginner’s Guide to SvelteKit
A Beginner’s Guide to SvelteKit
Erik KückelheimSimon Holthausen
Brighten Up Your Astro Site with KwesForms and Rive
Brighten Up Your Astro Site with KwesForms and Rive
Paul Scanlon
Which Programming Language Should I Learn First in 2024?
Which Programming Language Should I Learn First in 2024?
Joel Falconer
Managing PHP Versions with Laravel Herd
Managing PHP Versions with Laravel Herd
Dianne Pena
Accelerating the Cloud: The Final Steps
Accelerating the Cloud: The Final Steps
Dave Neary
An Alphebetized List of MIME Types
An Alphebetized List of MIME Types
Dianne Pena
The Best PHP Frameworks for 2024
The Best PHP Frameworks for 2024
Claudio Ribeiro
11 Best WordPress Themes for Developers & Designers in 2024
11 Best WordPress Themes for Developers & Designers in 2024
SitePoint Sponsors
Top 10 Best WordPress AI Plugins of 2024
Top 10 Best WordPress AI Plugins of 2024
Dianne Pena
20+ Tools for Node.js Development in 2024
20+ Tools for Node.js Development in 2024
Dianne Pena
The Best Figma Plugins to Enhance Your Design Workflow in 2024
The Best Figma Plugins to Enhance Your Design Workflow in 2024
Dianne Pena
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Christopher Collins
Build Your Own AI Tools in Python Using the OpenAI API
Build Your Own AI Tools in Python Using the OpenAI API
Zain Zaidi
The Best React Chart Libraries for Data Visualization in 2024
The Best React Chart Libraries for Data Visualization in 2024
Dianne Pena
7 Free AI Logo Generators to Get Started
7 Free AI Logo Generators to Get Started
Zain Zaidi
Turn Your Vue App into an Offline-ready Progressive Web App
Turn Your Vue App into an Offline-ready Progressive Web App
Imran Alam
Clean Architecture: Theming with Tailwind and CSS Variables
Clean Architecture: Theming with Tailwind and CSS Variables
Emmanuel Onyeyaforo
How to Analyze Large Text Datasets with LangChain and Python
How to Analyze Large Text Datasets with LangChain and Python
Matt Nikonorov
6 Techniques for Conditional Rendering in React, with Examples
6 Techniques for Conditional Rendering in React, with Examples
Yemi Ojedapo
Introducing STRICH: Barcode Scanning for Web Apps
Introducing STRICH: Barcode Scanning for Web Apps
Alex Suzuki
Using Nodemon and Watch in Node.js for Live Restarts
Using Nodemon and Watch in Node.js for Live Restarts
Craig Buckler
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form