This module is made for web servers using Node.js.

It can be imported using both CommonJS or ES module syntaxes.

📘

This documentation is for version 2.x.x

  • If you are running with version 1.x.x of the Node.js module, please follow this documentation.
  • If you are upgrading your integration from version 1.x.x to version 2.x.x, please follow this guide to ensure a successful migration.

Compatibility

  • Node.js >= 18.x

Prerequisites

Available modules

Integration with Express framework

Compatibility

  • Express >= 4.x

Installation

The module can be installed as an npm package:

npm install @datadome/module-express

Usage

const { DatadomeExpress } = require('@datadome/module-express');
const express = require('express');

const app = express();

const datadomeClient = new DatadomeExpress('Some Key');

app.use(datadomeClient.middleware());

app.get('/', function (req, res) {
  res.send('Hello World');
});

app.listen(3000);
import { DatadomeExpress } from '@datadome/module-express';
import express from 'express';

const app = express();

const datadomeClient = new DatadomeExpress('Some Key');

app.use(datadomeClient.middleware());

app.get('/', function (req, res) {
  res.send('Hello World');
});

app.listen(3000);

Integration with built-in HTTP module from Node.js

Installation

The module can be installed as an npm package:

npm install @datadome/module-http

Usage

const { DatadomeHttp } = require('@datadome/module-http');
const http = require('http');

const datadomeClient = new DatadomeHttp('Some Key');

const server = http.createServer(async (req, res) => {
  const { result, error } = await datadomeClient.handleRequest(req, res);
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
  } else {
    console.log('Request challenged');
  }
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
import { DatadomeHttp } from '@datadome/module-http';
import http from 'http';

const datadomeClient = new DatadomeHttp('Some Key');

const server = http.createServer(async (req, res) => {
  const { result, error } = await datadomeClient.handleRequest(req, res);
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
  } else {
    console.log('Request challenged');
  }
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Configuration

The module can be used with minimal configuration including only the server-side key:

const datadomeClient = new DatadomeExpress('Some Key');
const datadomeClient = new DatadomeHttp('Some Key');

Settings

Option nameDescriptionDefault value
timeoutTimeout in milliseconds, after which the request will be allowed.150
urlPatternInclusionRegex to match to process the request with the Protection API.
If null, all requests that don't match urlPatternExclusion will be processed.
null
urlPatternExclusionRegex to match to exclude requests from being processed with the Protection API.
If null, all requests will be processed.
\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map|json|avif|xml|gz|zip)$
endpointHostHost of the Protection API.'api.datadome.co'

Here is an example of configuration with default values that you can modify according to your needs:

const datadomeClient = new DatadomeExpress('Some Key', {
  timeout: 150,
  urlPatternInclusion: null,
  urlPatternExclusion: /\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map|json|avif|xml|gz|zip)$/i,
  endpointHost: 'api.datadome.co',
});
const datadomeClient = new DatadomeHttp('Some Key', {
  timeout: 150,
  urlPatternInclusion: null,
  urlPatternExclusion: /\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|js|map|json|avif|xml|gz|zip)$/i,
  endpointHost: 'api.datadome.co',
});

Advanced usage

Logging enriched headers

You can log the values of DataDome Enriched Headers after the handleRequest method has returned a result:

const { DatadomeExpress } = require('@datadome/module-express');
const express = require('express');

const app = express();

const datadomeClient = new DatadomeExpress('Some Key');

app.use(async (req, res, next) => {
  const { result, enrichedHeaders, error } = await datadomeClient.handleRequest(req, res);
  if (enrichedHeaders) {
    for (const [key, value] of Object.entries(enrichedHeaders)) {
      console.log(`Enriched header ${key}: ${value}`);
    }
  }
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    next();
  } else {
    console.log('Request challenged');
  }
});

app.get('/', function (req, res) {
  res.send('Hello World');
});

app.listen(3000);
const { DatadomeHttp } = require('@datadome/module-http');
const http = require('http');

const datadomeClient = new DatadomeHttp('Some Key');

const server = http.createServer(async (req, res) => {
  const { result, error, enrichedHeaders } = await datadomeClient.handleRequest(req, res);
  if (enrichedHeaders) {
    for (const [key, value] of Object.entries(enrichedHeaders)) {
      console.log(`Enriched header ${key}: ${value}`);
    }
  }
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
  } else {
    console.log('Request challenged');
  }
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Using nonce values for CSP

The HTTP Content-Security-Policy (CSP) script-src directive specifies valid sources for scripts to be loaded on a page.

If you are using this feature, you should provide the nonce field with a value generated by the application for each response:

const { DatadomeExpress } = require('@datadome/module-express');
const express = require('express');

const app = express();

const datadomeClient = new DatadomeExpress('Some Key');

const params = { nonce: 'your_value' };

// Usage with middleware method
app.use(datadomeClient.middleware(params));

// Usage with handleRequest method
app.use(async (req, res, next) => {
  const { result, enrichedHeaders, error } = await datadomeClient.handleRequest(req, res, params);
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    next();
  } else {
    console.log('Request challenged');
  }
});

app.get('/', function (req, res) {
  res.send('Hello World');
});

app.listen(3000);
const { DatadomeHttp } = require('@datadome/module-http');
const http = require('http');

const datadomeClient = new DatadomeHttp('Some Key');

const server = http.createServer(async (req, res) => {
  const params = { nonce: 'your_value' };
  const { result, error } = await datadomeClient.handleRequest(req, res, params);
  if (result === 'ALLOW') {
    console.log('Request allowed');
    if (error) {
      console.error(error);
    }
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World');
  } else {
    console.log('Request challenged');
  }
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});