Node.js7 min read

Input Validation with express-validator

Validate and sanitize user input in Express. Prevent security issues and ensure data integrity.

Sarah Chen
December 19, 2025
0.0k0

Input Validation with express-validator

Never trust user input. Validate everything.

Setup

npm install express-validator

Basic Validation

const { body, validationResult } = require('express-validator');

app.post('/api/users',
  body('email').isEmail(),
  body('password').isLength({ min: 6 }),
  (req, res) => {
    const errors = validationResult(req);
    
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    
    // Validation passed
    res.json({ message: 'User created' });
  }
);

Common Validators

body('email').isEmail(),
body('password').isLength({ min: 6, max: 100 }),
body('age').isInt({ min: 0, max: 120 }),
body('price').isFloat({ min: 0 }),
body('website').isURL(),
body('phone').isMobilePhone(),
body('date').isISO8601(),
body('uuid').isUUID(),
body('role').isIn(['user', 'admin']),
body('tags').isArray(),
body('name').notEmpty(),
body('bio').optional().isLength({ max: 500 }),

Custom Error Messages

body('email')
  .isEmail()
  .withMessage('Please enter a valid email'),
  
body('password')
  .isLength({ min: 6 })
  .withMessage('Password must be at least 6 characters'),

Sanitization

body('email').normalizeEmail(),
body('name').trim().escape(),
body('age').toInt(),
body('price').toFloat(),
body('tags').toArray(),

Chaining Validators

body('password')
  .trim()
  .isLength({ min: 8 })
  .withMessage('Password must be at least 8 characters')
  .matches(/[A-Z]/)
  .withMessage('Must contain uppercase letter')
  .matches(/[0-9]/)
  .withMessage('Must contain number'),

Custom Validators

body('confirmPassword').custom((value, { req }) => {
  if (value !== req.body.password) {
    throw new Error('Passwords do not match');
  }
  return true;
}),

body('email').custom(async (email) => {
  const user = await User.findOne({ email });
  if (user) {
    throw new Error('Email already in use');
  }
}),

Validating Params & Query

const { param, query } = require('express-validator');

// Route params
app.get('/api/users/:id',
  param('id').isMongoId(),
  (req, res) => { ... }
);

// Query strings
app.get('/api/search',
  query('q').notEmpty().trim(),
  query('page').optional().isInt({ min: 1 }),
  query('limit').optional().isInt({ min: 1, max: 100 }),
  (req, res) => { ... }
);

Reusable Validation Middleware

// validations/user.js
const { body } = require('express-validator');

const createUserValidation = [
  body('name')
    .trim()
    .notEmpty()
    .withMessage('Name is required')
    .isLength({ max: 100 }),
  body('email')
    .isEmail()
    .normalizeEmail()
    .withMessage('Valid email required'),
  body('password')
    .isLength({ min: 8 })
    .withMessage('Password must be 8+ characters')
];

const updateUserValidation = [
  body('name').optional().trim().isLength({ max: 100 }),
  body('email').optional().isEmail().normalizeEmail()
];

module.exports = { createUserValidation, updateUserValidation };

Validation Middleware

// middleware/validate.js
const { validationResult } = require('express-validator');

const validate = (req, res, next) => {
  const errors = validationResult(req);
  
  if (!errors.isEmpty()) {
    return res.status(400).json({
      status: 'error',
      errors: errors.array().map(err => ({
        field: err.path,
        message: err.msg
      }))
    });
  }
  
  next();
};

module.exports = validate;

Complete Example

const { createUserValidation } = require('./validations/user');
const validate = require('./middleware/validate');

app.post('/api/users',
  createUserValidation,
  validate,
  async (req, res) => {
    // All validation passed
    const user = await User.create(req.body);
    res.status(201).json(user);
  }
);

Key Takeaway

Always validate user input. Use express-validator for declarative validation. Sanitize data to prevent XSS. Create reusable validation arrays. Return clear error messages. It's your first line of defense against bad data.

#Node.js#Express#Validation#Security#Intermediate