# How to Write Ghidra Scripts in Java vs Python Using PyGhidra

> Learn to write Ghidra scripts in Java versus Python. Explore PyGhidra for native Python scripting with full Ghidra API access via an automatic bridge.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Write Ghidra scripts in Java by compiling classes that extend `GhidraScript`, or use PyGhidra to run native Python 3 code with full access to Ghidra's Java API through an automatic bridge.**

Ghidra's reverse engineering framework supports multiple scripting languages through a provider-based architecture implemented in the NationalSecurityAgency/ghidra repository. Whether you choose Java for tight JVM integration or Python for rapid prototyping with scientific libraries, both approaches leverage the same underlying `ghidra.app.script.GhidraScript` base class. This guide explains how to write Ghidra scripts in both languages and when to use each approach.

## Understanding Ghidra's Script Architecture

All Ghidra scripts inherit from the abstract class `ghidra.app.script.GhidraScript` located in [`Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java). This base class provides the **FlatProgramAPI**—giving you access to `currentProgram`, `println`, `askString`, and other utilities—plus the abstract `run()` method you must implement.

The framework uses the **GhidraScriptProvider** extension point to map file extensions to runtime environments. Each provider lives in a specific source file:

- [`JavaScriptProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/JavaScriptProvider.java) handles `.java` files
- [`JythonScriptProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/JythonScriptProvider.java) handles Jython-specific scripts  
- [`PyGhidraScriptProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/PyGhidraScriptProvider.java) handles native Python 3 scripts

When you place a script in a script directory, `GhidraScriptUtil.getProvider(file)`—implemented in [`Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java)—iterates through registered providers to find a match. You can override the default selection by adding a runtime metadata comment such as `# @runtime Jython` at the top of your file.

## Writing Ghidra Scripts in Java

Java scripts are first-class citizens in Ghidra. To create one, extend `GhidraScript` and implement the `run()` method. The `JavaScriptProvider`—located in [`Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/app/script/JavaScriptProvider.java)—compiles your source on-the-fly using the same JDK that runs Ghidra.

```java
import ghidra.app.script.GhidraScript;

public class HelloWorld extends GhidraScript {
    @Override
    public void run() throws Exception {
        println("Hello from Java!");
        // Example: list all functions in the current program
        for (Function f : currentProgram.getFunctionManager().getFunctions(true)) {
            println("Function: " + f.getName() + " @ " + f.getEntryPoint());
        }
    }
}

```

**Key characteristics of Java scripts:**

- **Compilation**: Performed on-the-fly by `JavaScriptProvider`. Errors appear in the script console.
- **API Access**: Direct Java calls with no bridging overhead.
- **Packaging**: Bundle multiple scripts into a Ghidra Extension using the Extension descriptor.
- **Performance**: Comparable to native plugins because it runs inside the same JVM.

## Writing Ghidra Scripts in Python with PyGhidra

PyGhidra, available since Ghidra 10.2, provides a native CPython 3 interpreter that bridges to Ghidra's Java API. The `PyGhidraScriptProvider`—located in [`Ghidra/Features/PyGhidra/src/main/java/ghidra/pyghidra/PyGhidraScriptProvider.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/PyGhidra/src/main/java/ghidra/pyghidra/PyGhidraScriptProvider.java)—handles `.py` files by default when PyGhidra is installed.

### How PyGhidra Works

PyGhidra uses a JNI-based bridge to expose Ghidra's Java classes to Python. When you run a script, the provider launches a native Python process and injects a `this` object that represents the `GhidraScript` instance. This gives you access to `println`, `currentProgram`, and other FlatProgramAPI methods.

### Basic PyGhidra Script Structure

Create a `.py` file in your script directory. Unlike Jython scripts, you do not need a `@runtime` header unless you specifically want to force Jython. Import Java classes through the bridge using `this.getClass().forName` or access them directly via the `ghidra` module.

```python

# PyGhidra scripts get a `this` object that is the GhidraScript instance.

# It provides the same methods as the Java base class.

this.println("Hello from PyGhidra!")

# Access Java types via the pyjnius-style bridge

Function = this.getClass().forName("ghidra.program.model.listing.Function")
funcMgr = currentProgram.getFunctionManager()

# Iterate over functions (identical to the Java version)

for f in funcMgr.getFunctions(True):
    this.println(f"Function: {f.getName()} @ {f.getEntryPoint()}")

```

**Key characteristics of PyGhidra scripts:**

- **Interpreter**: Native CPython 3 launched by `PyGhidraScriptProvider`.
- **Bridge**: `pyghidra` creates Python wrappers for Java classes automatically.
- **`this` Object**: Mirrors the Java `GhidraScript` instance; access via `this.println`, `this.currentProgram`, etc.
- **No `@runtime` needed**: PyGhidra is the default for `.py` files when installed.
- **Performance**: Slightly slower than Java due to the CPython ↔ JVM bridge, but sufficient for most analysis.
- **Virtual Environments**: Respects active Python virtual environments for third-party packages.

## Choosing Between Java and PyGhidra

Select your language based on performance requirements and ecosystem needs:

- **Java**: Choose when you need maximum performance, tight integration with Ghidra internals, or plan to distribute your scripts as a Ghidra Extension. Java scripts compile to bytecode and run directly in the same JVM as Ghidra, eliminating bridging overhead.
- **PyGhidra**: Choose when you need rapid prototyping, access to Python's scientific ecosystem (NumPy, pandas, etc.), or prefer Python syntax. PyGhidra runs in native CPython 3, allowing you to install packages via pip while still accessing the full Ghidra Java API.

## Summary

- Ghidra scripts inherit from `ghidra.app.script.GhidraScript` regardless of language.
- Java scripts use `JavaScriptProvider` for on-the-fly compilation and direct JVM execution.
- PyGhidra scripts use `PyGhidraScriptProvider` to run native Python 3 with automatic Java bridging.
- Use the `# @runtime` metadata comment to force Jython if needed.

- Store scripts in the script directories (e.g., `$GHIDRA_HOME/ghidra_scripts`) to make them available in the Script Manager.

## Frequently Asked Questions

### Can I mix Java and Python scripts in the same Ghidra project?

Yes. The `GhidraScriptUtil` class automatically detects the appropriate `GhidraScriptProvider` based on file extension and metadata. You can store `.java` and `.py` files side-by-side in the same script directory; Ghidra will compile Java scripts with `JavaScriptProvider` and execute Python scripts with `PyGhidraScriptProvider` (or `JythonScriptProvider` if specified).

### Do I need to install PyGhidra separately?

No. PyGhidra has been bundled with Ghidra since version 10.2. The `PyGhidraScriptProvider` is registered automatically when you install Ghidra, and it handles `.py` files by default. However, you must have a compatible Python 3 installation available on your system path for the bridge to function.

### How do I force a Python script to use Jython instead of PyGhidra?

Add the metadata comment `# @runtime Jython` as the first line of your script. When `GhidraScriptUtil.getProvider(file)` scans the file, it detects this directive and routes the script to `JythonScriptProvider` instead of `PyGhidraScriptProvider`. This is useful for maintaining legacy scripts that depend on Jython-specific behaviors.

### Is there a performance difference between Java and PyGhidra scripts?

Yes. Java scripts run directly in the same JVM as Ghidra through `JavaScriptProvider`, offering native performance with no bridging overhead. PyGhidra scripts run in a separate native CPython 3 process and cross the JNI bridge for every Java API call, introducing slight latency. For most analysis tasks the difference is negligible, but for processing millions of instructions, Java is preferable.