Chrome Extension Manifest Content Scripts Config — Best Practices

4 min read

Content Script Manifest Configuration Patterns

This guide covers optimization patterns for the content_scripts field in manifest.json.

URL Targeting: matches and exclude_matches

The matches field uses match patterns to define which pages load your content script.

{
  "content_scripts": [{
    "matches": ["*://example.com/*", "*://www.example.com/*"],
    "exclude_matches": ["*://example.com/admin/*"],
    "js": ["content.js"]
  }]
}

run_at Options

Controls when the content script injects relative to page load:

Option Timing Use Case
document_start Before any DOM content CSS injection, intercepting requests
document_idle (default) After DOM ready Most common, full page access
document_end After DOM parsed, resources may still load Late-stage modifications
{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "run_at": "document_start",
    "js": ["early-inject.js"]
  }]
}

Multiple Content Script Entries

Define separate entries for different sites to keep scripts focused:

{
  "content_scripts": [
    {
      "matches": ["*://site-a.com/*"],
      "js": ["site-a.js"]
    },
    {
      "matches": ["*://site-b.com/*"],
      "js": ["site-b.js"]
    }
  ]
}

CSS Injection

Use the separate css array for stylesheet injection:

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "css": ["styles.css"],
    "js": ["content.js"]
  }]
}

CSS loads before JS by default. Use css for page styling and js for interactivity.

all_frames Option

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "all_frames": true,
    "js": ["iframe-handler.js"]
  }]
}

match_about_blank

Injects into about:blank frames created by matched pages:

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "match_about_blank": true,
    "js": ["blank-inject.js"]
  }]
}

world Property

Controls the JavaScript execution context:

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "world": "MAIN",
    "js": ["page-context.js"]
  }]
}

Multiple JS Files

Multiple files in a single entry load in order and share the same scope:

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "js": ["utils.js", "main.js", "features.js"]
  }]
}

Glob Patterns

Use include_globs and exclude_globs for finer URL control:

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "include_globs": ["*article*", "*post*"],
    "exclude_globs": ["*draft*"],
    "js": ["content.js"]
  }]
}

Performance Impact

Each content script entry adds overhead on matching pages:

Combining Static and Dynamic

See Dynamic Scripts for implementation details.

Common Configurations

Site-Specific

{
  "content_scripts": [{
    "matches": ["*://docs.example.com/*"],
    "js": ["docs-enhancer.js"]
  }]
}

Broad Matching

{
  "content_scripts": [{
    "matches": ["http://*/*", "https://*/*"],
    "js": ["global-tool.js"]
  }]
}

Selective Paths

{
  "content_scripts": [{
    "matches": ["*://example.com/*"],
    "include_globs": ["/api/*"],
    "js": ["api-helper.js"]
  }]
}

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.