---
title: "script:updated Hook"
description: "Internal hook emitted when a managed script starts loading, loads, fails, or is removed."
canonical_url: "https://unhead.unjs.io/docs/head/api/hooks/script-updated"
last_updated: "2026-08-11T00:38:02.464Z"
---

The `script:updated` hook is emitted when a `useScript()` instance changes to `loading`, `loaded`, `error`, or `removed`. A new script starts in `awaitingLoad`, but creating it does not emit this hook until its status changes.

This hook also drives `useScript()`'s internal load promise and callbacks. Application code should normally use `onLoaded()`, `onError()`, `load()`, and `remove()` on the returned script instance instead.

## Hook Signature

```ts
export interface Hook {
  'script:updated': (ctx: {
    script: ScriptInstance<any>
  }) => void | Promise<void>
}
```

### Script Status

```ts
type UseScriptStatus =
  | 'awaitingLoad'
  | 'loading'
  | 'loaded'
  | 'error'
  | 'removed'
```

`ScriptInstance` exposes `id`, `status`, `instance`, `proxy`, `signal`, `entry`, `load()`, `warmup()`, `remove()`, `setupTriggerHandler()`, `onLoaded()`, and `onError()`. The status is read-only in the public type. Retry counters, fallback sources, loading timestamps, and an `error` property are not part of this API.

## Usage Example

```ts
import { defineHeadPlugin } from '@unhead/dynamic-import/plugins'

export const scriptStatusPlugin = defineHeadPlugin({
  key: 'script-status',
  hooks: {
    'script:updated': ({ script }) => {
      console.log(`Script ${script.id}: ${script.status}`)
    }
  }
})
```

Hook promises are not used to delay script loading or status transitions.
