# How to Use frp Client Plugins for HTTP Proxy and Static File Serving

> Learn how to use frp client plugins for HTTP proxy and static file serving. Tunnel traffic and serve local directories without extra software.

- Repository: [fatedier/frp](https://github.com/fatedier/frp)
- Tags: how-to-guide
- Published: 2026-02-26

---

**frp client plugins enable the frpc binary to tunnel traffic through upstream HTTP proxies and serve local directories as static web servers without installing separate software like Nginx or Squid.**

The fatedier/frp repository ships with a built-in **client-side plugin system** that extends frpc beyond raw TCP/UDP forwarding. By configuring these plugins in your TOML configuration files, you can route connections through corporate HTTP proxies or expose filesystem directories via HTTP directly from the client host.

## How frp Client Plugins Work

The plugin architecture in frp follows a strict registration and implementation pattern defined in the source code.

### Plugin Type Registration

When frpc parses its configuration, it maps plugin type strings to concrete Go structs using the `clientPluginOptionsTypeMap` defined in [[`pkg/config/v1/proxy_plugin.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/proxy_plugin.go)](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go). This registry links the user-facing `type` field to the appropriate options structure:

```go
var clientPluginOptionsTypeMap = map[string]reflect.Type{
    PluginHTTPProxy:        reflect.TypeOf(HTTPProxyPluginOptions{}),
    PluginStaticFile:       reflect.TypeOf(StaticFilePluginOptions{}),
    // …
}

```

### Configuration Unmarshalling

Each plugin type has a dedicated options struct that defines valid configuration fields. The `HTTPProxyPluginOptions` and `StaticFilePluginOptions` structs, also located in [[`pkg/config/v1/proxy_plugin.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/proxy_plugin.go)](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go), specify the JSON/TOML keys available to users:

```go
type HTTPProxyPluginOptions struct {
    Type         string `json:"type,omitempty"`
    HTTPUser     string `json:"httpUser,omitempty"`
    HTTPPassword string `json:"httpPassword,omitempty"`
}

type StaticFilePluginOptions struct {
    Type         string `json:"type,omitempty"`
    LocalPath    string `json:"localPath,omitempty"`
    StripPrefix  string `json:"stripPrefix,omitempty"`
    HTTPUser     string `json:"httpUser,omitempty"`
    HTTPPassword string `json:"httpPassword,omitempty"`
}

```

### Runtime Implementation

During client startup, frpc instantiates the plugin implementation based on the configured `type`. The **http_proxy** logic resides in [[`pkg/plugin/client/http_proxy.go`](https://github.com/fatedier/frp/blob/main/pkg/plugin/client/http_proxy.go)](https://github.com/fatedier/frp/blob/dev/pkg/plugin/client/http_proxy.go), while the **static_file** logic is in [[`pkg/plugin/client/static_file.go`](https://github.com/fatedier/frp/blob/main/pkg/plugin/client/static_file.go)](https://github.com/fatedier/frp/blob/dev/pkg/plugin/client/static_file.go). Both satisfy the `ClientPlugin` interface, intercepting inbound connections from the frps server to perform proxy negotiation or HTTP file serving before forwarding data.

## Configuring the HTTP Proxy Plugin

The **http_proxy** plugin routes frpc's outbound traffic through an upstream HTTP, HTTPS, SOCKS5, or NTLM proxy. This is essential for environments where direct internet access is blocked and all traffic must traverse a corporate proxy server.

Add the plugin to your [`frpc.toml`](https://github.com/fatedier/frp/blob/main/frpc.toml) by defining a TCP proxy with a nested `[proxies.plugin]` table:

```toml
[[proxies]]
name = "http_proxy"
type = "tcp"
remotePort = 6000

[proxies.plugin]
type = "http_proxy"
httpUser = "proxy_username"
httpPassword = "proxy_password"

```

- Set the upstream proxy address via the `transport.proxyURL` field in your client configuration or the `http_proxy` environment variable.
- The `httpUser` and `httpPassword` fields map to `HTTPUser` and `HTTPPassword` in `HTTPProxyPluginOptions`, providing credentials for proxy authentication.
- When active, frpc forwards all traffic arriving at `remotePort` through the configured upstream proxy before reaching the final destination.

## Configuring the Static File Plugin

The **static_file** plugin transforms frpc into a lightweight HTTP file server, exposing a local directory to the internet without requiring Apache or Nginx.

Configure the plugin in [`frpc.toml`](https://github.com/fatedier/frp/blob/main/frpc.toml) by specifying the directory path and optional access controls:

```toml
[[proxies]]
name = "static_file"
type = "tcp"
remotePort = 6006

[proxies.plugin]
type = "static_file"
localPath = "/var/www/blog"
stripPrefix = "static"
httpUser = "admin"
httpPassword = "secret"

```

- **`localPath`**: Required. Specifies the absolute path to the directory on the client machine that will be served.
- **`stripPrefix`**: Optional. Removes the specified prefix from the request URL before mapping to the filesystem (e.g., requesting [`/static/file.txt`](https://github.com/fatedier/frp/blob/main//static/file.txt) serves [`/var/www/blog/file.txt`](https://github.com/fatedier/frp/blob/main//var/www/blog/file.txt) when `stripPrefix = "static"`).
- **`httpUser` and `httpPassword`**: Optional. Enables HTTP Basic Authentication, prompting browsers for credentials before serving files.

When frpc runs with this configuration, visiting `http://<frps_host>:6006/static/` serves the contents of `/var/www/blog` on the client host.

## Summary

- **frp client plugins** are declared in `[proxies.plugin]` tables within frpc TOML/YAML/JSON configuration files, as shown in [[`conf/frpc_full_example.toml`](https://github.com/fatedier/frp/blob/main/conf/frpc_full_example.toml)](https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml).
- The **http_proxy** plugin, implemented in [`pkg/plugin/client/http_proxy.go`](https://github.com/fatedier/frp/blob/main/pkg/plugin/client/http_proxy.go), tunnels connections through upstream proxies using the `HTTPProxyPluginOptions` struct.
- The **static_file** plugin, implemented in [`pkg/plugin/client/static_file.go`](https://github.com/fatedier/frp/blob/main/pkg/plugin/client/static_file.go), serves local directories via HTTP using `StaticFilePluginOptions`, supporting path stripping and basic authentication.
- Both plugins integrate seamlessly with frp's transport layer (TCP, KCP, QUIC, WebSocket) and can coexist with standard TCP/UDP proxies in a single frpc instance.

## Frequently Asked Questions

### Can I use multiple frp client plugins in a single frpc instance?

Yes. Each `[[proxies]]` block in your configuration is independent. You can define one proxy using the `http_proxy` plugin and another using the `static_file` plugin within the same [`frpc.toml`](https://github.com/fatedier/frp/blob/main/frpc.toml) file, and frpc will initialize both plugins during startup according to the `clientPluginOptionsTypeMap` logic.

### Does the HTTP proxy plugin support SOCKS5 or NTLM authentication?

Yes. The implementation in [`pkg/plugin/client/http_proxy.go`](https://github.com/fatedier/frp/blob/main/pkg/plugin/client/http_proxy.go) handles negotiation with upstream HTTP proxies, SOCKS5 proxies, and NTLM proxies. You provide credentials via the `httpUser` and `httpPassword` fields in the plugin configuration, which correspond to the `HTTPUser` and `HTTPPassword` fields in the source struct.

### How do I remove URL path prefixes when serving static files?

Use the `stripPrefix` parameter in your `static_file` plugin configuration. This field in `StaticFilePluginOptions` tells the plugin to remove the specified prefix from the incoming request path before resolving it against the `localPath` directory. For example, with `stripPrefix = "docs"` and `localPath = "/files"`, a request to [`/docs/readme.txt`](https://github.com/fatedier/frp/blob/main//docs/readme.txt) serves [`/files/readme.txt`](https://github.com/fatedier/frp/blob/main//files/readme.txt).

### Where are the plugin options defined in the frp source code?

Plugin option structs are defined in [[`pkg/config/v1/proxy_plugin.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/proxy_plugin.go)](https://github.com/fatedier/frp/blob/dev/pkg/config/v1/proxy_plugin.go). The `HTTPProxyPluginOptions` and `StaticFilePluginOptions` structs specify the available configuration fields (such as `localPath`, `stripPrefix`, `httpUser`, and `httpPassword`) and are mapped to type strings via the `clientPluginOptionsTypeMap` variable.