How to debug Node.js with Chrome DevTools
Chrome DevTools provides powerful visual debugging for Node.js with breakpoints, step-through execution, variable inspection, and performance profiling. As the creator of CoreUI, a widely used open-source UI library, I’ve debugged production Node.js issues using Chrome DevTools throughout my 11 years of backend development. The most effective approach is running Node.js with –inspect flag and connecting Chrome DevTools for full debugging capabilities. This method enables setting breakpoints, watching variables, profiling CPU and memory, and analyzing async operations with familiar browser DevTools interface.
Start Node.js with –inspect flag and open chrome://inspect in Chrome to connect DevTools debugger.
// server.js
const express = require('express')
const app = express()
app.use(express.json())
const users = [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' }
]
app.get('/api/users', (req, res) => {
// Set breakpoint here in Chrome DevTools
const page = parseInt(req.query.page) || 1
const limit = parseInt(req.query.limit) || 10
const startIndex = (page - 1) * limit
const endIndex = startIndex + limit
const paginatedUsers = users.slice(startIndex, endIndex)
res.json({
page,
limit,
total: users.length,
users: paginatedUsers
})
})
app.post('/api/users', (req, res) => {
// Breakpoint here to inspect req.body
const newUser = {
id: users.length + 1,
name: req.body.name,
email: req.body.email
}
users.push(newUser)
res.status(201).json(newUser)
})
async function fetchExternalData(userId) {
// Breakpoint to debug async operations
console.log('Fetching data for user:', userId)
await new Promise(resolve => setTimeout(resolve, 1000))
return {
userId,
preferences: { theme: 'dark', notifications: true }
}
}
app.get('/api/users/:id/preferences', async (req, res) => {
try {
const userId = parseInt(req.params.id)
// Watch this async call in DevTools
const data = await fetchExternalData(userId)
res.json(data)
} catch (error) {
// Breakpoint to inspect error details
console.error('Error fetching preferences:', error)
res.status(500).json({ error: error.message })
}
})
app.listen(3000, () => {
console.log('Server running on http://localhost:3000')
console.log('Debugger listening - open chrome://inspect')
})
Start debugging:
# Start with inspector (debugger listens but doesn't break)
node --inspect server.js
# Start and break on first line (wait for debugger)
node --inspect-brk server.js
# Custom inspector port
node --inspect=0.0.0.0:9229 server.js
Steps to debug in Chrome DevTools:
- Start Node.js with –inspect flag
- Open Chrome and navigate to chrome://inspect
- Click “inspect” under your Node.js process
- DevTools opens with Sources tab showing your code
- Set breakpoints by clicking line numbers
- Trigger the code path (make API request)
- Execution pauses at breakpoint
- Use debugging controls:
- Resume (F8): Continue execution
- Step over (F10): Execute current line
- Step into (F11): Enter function calls
- Step out (Shift+F11): Exit current function
- Inspect variables in Scope panel
- Add watch expressions for specific values
- View call stack to trace execution path
Here the –inspect flag starts Node.js inspector protocol on default port 9229. Chrome DevTools connects via WebSocket to the inspector for real-time debugging. Breakpoints pause execution allowing variable inspection and step-through debugging. The Sources panel displays all loaded files with syntax highlighting. The Scope panel shows local, closure, and global variables at breakpoint. Watch expressions monitor specific variable values across execution. The Call Stack panel traces function calls leading to current execution point. Async operations are tracked with async stack traces enabled.
Best Practice Note:
This is the Chrome DevTools debugging workflow we use in CoreUI Node.js development for complex issue investigation and performance optimization. Use the Performance tab to profile CPU usage and identify bottlenecks, enable async stack traces in DevTools settings for better async debugging, and use the Memory tab to detect memory leaks by taking heap snapshots and comparing allocations across different execution states.



