This guide covers advanced techniques for using the Nuclei SDK efficiently and effectively.
Thread-safe concurrent scanning
The ThreadSafeNucleiEngine allows running multiple scans concurrently with goroutines:
import (
" context "
nuclei " github.com/projectdiscovery/nuclei/v3/lib "
" github.com/projectdiscovery/nuclei/v3/pkg/installer "
syncutil " github.com/projectdiscovery/utils/sync "
)
func main () {
ctx := context . Background ()
// Pre-install templates for concurrent usage
tm := installer . TemplateManager {}
if err := tm . FreshInstallIfNotExists (); err != nil {
panic ( err )
}
// Create thread-safe engine
ne , err := nuclei . NewThreadSafeNucleiEngineCtx ( ctx )
if err != nil {
panic ( err )
}
defer ne . Close ()
// Use sized waitgroup for concurrency control
sg , err := syncutil . New ( syncutil . WithSize ( 10 ))
if err != nil {
panic ( err )
}
// Scan 1: DNS templates
sg . Add ()
go func () {
defer sg . Done ()
err = ne . ExecuteNucleiWithOpts (
[] string { "scanme.sh" },
nuclei . WithTemplateFilters ( nuclei . TemplateFilters {
ProtocolTypes : "dns" ,
}),
nuclei . WithHeaders ([] string { "X-Bug-Bounty: pdteam" }),
nuclei . EnablePassiveMode (),
)
if err != nil {
panic ( err )
}
}()
// Scan 2: OAST templates
sg . Add ()
go func () {
defer sg . Done ()
err = ne . ExecuteNucleiWithOpts (
[] string { "http://honey.scanme.sh" },
nuclei . WithTemplateFilters ( nuclei . TemplateFilters {
Tags : [] string { "oast" },
}),
)
if err != nil {
panic ( err )
}
}()
// Wait for all scans to finish
sg . Wait ()
}
ThreadSafeNucleiEngine does not support all options. Methods like EnableStatsWithOpts, WithVerbosity, and UseOutputWriter will return ErrOptionsNotSupported when used after initialization.
Dynamic speed control
Adjust scanning speed dynamically during execution:
import (
" context "
" time "
nuclei " github.com/projectdiscovery/nuclei/v3/lib "
)
func main () {
ne , err := nuclei . NewNucleiEngineCtx (
context . TODO (),
nuclei . WithTemplateFilters ( nuclei . TemplateFilters {
Tags : [] string { "oast" },
}),
nuclei . WithGlobalRateLimit ( 1 , time . Second ),
nuclei . WithConcurrency ( nuclei . Concurrency {
TemplateConcurrency : 1 ,
HostConcurrency : 1 ,
HeadlessHostConcurrency : 1 ,
HeadlessTemplateConcurrency : 1 ,
JavascriptTemplateConcurrency : 1 ,
TemplatePayloadConcurrency : 1 ,
ProbeConcurrency : 1 ,
}),
)
if err != nil {
panic ( err )
}
defer ne . Close ()
ne . LoadTargets ([] string { "http://honey.scanme.sh" }, false )
// Start scan in background
go func () {
err := ne . ExecuteWithCallback ( nil )
if err != nil {
panic ( err )
}
}()
// Wait and then increase rate limit
time . Sleep ( 5 * time . Second )
ne . Options (). RateLimit = 5000
// Wait and then increase concurrency
time . Sleep ( 5 * time . Second )
ne . Options (). TemplateThreads = 25
ne . Options (). BulkSize = 25
time . Sleep ( 30 * time . Second )
}
Custom template loading
Load specific templates
ne , err := nuclei . NewNucleiEngine (
nuclei . WithTemplatesOrWorkflows ( nuclei . TemplateSources {
Templates : [] string {
"/path/to/template1.yaml" ,
"/path/to/templates/directory" ,
},
Workflows : [] string {
"/path/to/workflow.yaml" ,
},
}),
)
Load remote templates
ne , err := nuclei . NewNucleiEngine (
nuclei . WithTemplatesOrWorkflows ( nuclei . TemplateSources {
RemoteTemplates : [] string {
"https://example.com/template.yaml" ,
},
TrustedDomains : [] string {
"example.com" ,
},
}),
)
Template parsing and signing
Parse templates
templateData := [] byte ( `
id: custom-template
info:
name: Custom Template
severity: high
http:
- method: GET
path:
- "{{BaseURL}}"
` )
tmpl , err := ne . ParseTemplate ( templateData )
if err != nil {
panic ( err )
}
fmt . Printf ( "Template verified: %v \n " , tmpl . Verified )
Sign templates
import " github.com/projectdiscovery/nuclei/v3/pkg/templates/signer "
// Create signer
tmplSigner := & signer . TemplateSigner {}
// Sign template
signedData , err := ne . SignTemplate ( tmplSigner , templateData )
if err != nil {
panic ( err )
}
Advanced filtering
Complex filter combinations
ne , err := nuclei . NewNucleiEngine (
nuclei . WithTemplateFilters ( nuclei . TemplateFilters {
Severity : "high,critical" ,
ExcludeSeverities : "info" ,
Tags : [] string { "cve" , "rce" },
ExcludeTags : [] string { "dos" , "intrusive" },
ProtocolTypes : "http,dns" ,
ExcludeProtocolTypes : "code" ,
Authors : [] string { "pdteam" },
IDs : [] string { "CVE-2021-44228" },
ExcludeIDs : [] string { "test-template" },
}),
)
DSL template conditions
ne , err := nuclei . NewNucleiEngine (
nuclei . WithTemplateFilters ( nuclei . TemplateFilters {
TemplateCondition : [] string {
"contains(tags, 'cve') && severity == 'critical'" ,
},
}),
)
Network configuration
ne , err := nuclei . NewNucleiEngine (
nuclei . WithNetworkConfig ( nuclei . NetworkConfig {
Timeout : 30 ,
Retries : 3 ,
LeaveDefaultPorts : true ,
Interface : "eth0" ,
SourceIP : "192.168.1.100" ,
SystemResolvers : false ,
InternalResolversList : [] string { "1.1.1.1" , "8.8.8.8" },
MaxHostError : 30 ,
DisableMaxHostErr : false ,
TrackError : [] string { "timeout" , "no-address" },
}),
)
Interactsh integration
import " github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh "
ne , err := nuclei . NewNucleiEngine (
nuclei . WithInteractshOptions ( nuclei . InteractshOpts {
ServerURL : "https://interact.sh" ,
CacheSize : 5000 ,
Eviction : 60 ,
CooldownPeriod : 5 ,
PollDuration : 5 ,
}),
)
Headless browser support
ne , err := nuclei . NewNucleiEngine (
nuclei . EnableHeadlessWithOpts ( & nuclei . HeadlessOpts {
PageTimeout : 20 ,
ShowBrowser : false ,
UseChrome : false ,
HeadlessOptions : [] string {
"--no-sandbox" ,
"--disable-gpu" ,
},
}),
)
Enabling headless mode may open up attack surface due to browser usage and can be prone to exploitation by custom unverified templates if not properly configured.
Stats and metrics
ne , err := nuclei . NewNucleiEngine (
nuclei . EnableStatsWithOpts ( nuclei . StatsOptions {
Interval : 5 , // seconds
JSON : true ,
MetricServerPort : 6064 ,
}),
)
Access metrics at http://localhost:6064/metrics
Custom output writers
import (
" github.com/projectdiscovery/nuclei/v3/pkg/output "
)
type CustomWriter struct {
// Your custom implementation
}
func ( w * CustomWriter ) Write ( event * output . ResultEvent ) error {
// Custom write logic
return nil
}
func ( w * CustomWriter ) Close () {}
writer := & CustomWriter {}
ne , err := nuclei . NewNucleiEngine (
nuclei . UseOutputWriter ( writer ),
)
Proxy configuration
ne , err := nuclei . NewNucleiEngine (
nuclei . WithProxy (
[] string { "http://proxy.example.com:8080" },
true , // proxy internal requests
),
)
Custom variables
ne , err := nuclei . NewNucleiEngine (
nuclei . WithVars ([] string {
"api_key=secret123" ,
"base_url=https://api.example.com" ,
}),
)
Use in templates:
http :
- method : GET
path :
- "{{base_url}}/endpoint"
headers :
Authorization : "Bearer {{api_key}}"
Authentication providers
import " github.com/projectdiscovery/nuclei/v3/pkg/authprovider "
type CustomAuthProvider struct {
// Your implementation
}
ne , err := nuclei . NewNucleiEngine (
nuclei . WithAuthProvider ( & CustomAuthProvider {}),
)
Secrets management
ne , err := nuclei . NewNucleiEngine (
nuclei . LoadSecretsFromFile (
[] string { "/path/to/secrets.yaml" },
true , // prefetch secrets
),
)
Scan strategies
// Host-spray mode (default)
ne , err := nuclei . NewNucleiEngine (
nuclei . WithScanStrategy ( "host-spray" ),
)
// Template-spray mode
ne , err := nuclei . NewNucleiEngine (
nuclei . WithScanStrategy ( "template-spray" ),
)
Accessing internal components
Get loaded templates
templates := ne . GetTemplates ()
workflows := ne . GetWorkflows ()
fmt . Printf ( "Loaded %d templates and %d workflows \n " ,
len ( templates ), len ( workflows ))
Get executor options
execOpts := ne . GetExecuterOptions ()
fmt . Printf ( "Rate limit: %d \n " , execOpts . RateLimiter . GetLimit ())
Get engine options
opts := ne . Options ()
fmt . Printf ( "Template threads: %d \n " , opts . TemplateThreads )
Access core engine
engine := ne . Engine ()
workPool := engine . GetWorkPool ()
Cluster template mappings
// Get templates in a cluster
templateIDs := ne . GetClusterTemplateIDs ( "http-get" )
fmt . Printf ( "Templates in cluster: %v \n " , templateIDs )
// Get all cluster mappings
mappings := ne . GetAllClusterMappings ()
for clusterID , templateIDs := range mappings {
fmt . Printf ( "Cluster %s : %v \n " , clusterID , templateIDs )
}
Resume support
ne , err := nuclei . NewNucleiEngine (
nuclei . WithResumeFile ( "/tmp/nuclei-resume.cfg" ),
)
DAST mode
// Only run DAST templates
ne , err := nuclei . NewNucleiEngine (
nuclei . DASTMode (),
)
Passive mode
// Process HTTP responses without sending requests
ne , err := nuclei . NewNucleiEngine (
nuclei . EnablePassiveMode (),
)
Response size limits
ne , err := nuclei . NewNucleiEngine (
nuclei . WithResponseReadSize ( 10485760 ), // 10MB
)
Best practices
Pre-install templates when using ThreadSafeNucleiEngine
Use sized waitgroups to control concurrency
Implement proper error handling in goroutines
Set appropriate timeouts with context
Monitor resource usage with stats when running at scale
Use template filters to reduce unnecessary scans
Configure rate limiting to avoid overwhelming targets
Adjust concurrency : Tune TemplateConcurrency and HostConcurrency based on your resources
Use template clustering : Nuclei automatically clusters identical requests
Enable caching : Keep default template caching enabled for better performance
Filter early : Use strict template filters to reduce the number of templates loaded
Batch targets : Load multiple targets at once instead of one-by-one
Use thread-safe mode : For parallel scanning of different target groups
Next steps
Configuration options Complete reference of all options
API reference Detailed API documentation