Problem Overview: S7-1200 Data Log Auto-Download Failure
Engineers integrating S7-1200 CPUs (firmware 4.x and 2.8.x) into supervisory or historian systems frequently hit a wall when attempting to script the retrieval of CSV data logs. The native web server of the S7-1200 exposes data logs under the /DataLogs/ directory through its FileBrowser page, but a security check introduced in the firmware blocks automated clients. The browser-based download works; the same GET /FileBrowser/Download?Path=/DataLogs/<file>.csv request issued from a script returns:
"File operation not permitted - no referrer"
The same error appears on S7-1200 (CPU 1214C DC/DC/DC, order number 6ES7 214-1AG40-0XB0) and S7-1500 (e.g., CPU 1511T-1 PN, firmware V2.8.2) when no Referer header is supplied. The data log file is created on disk (size > 0) but the payload returned is the HTML of the web server login page, or the request is rejected outright with HTTP 403. The error is independent of the host operating system: it reproduces on Windows 7 x64, Windows 10/11, Windows XP, and most Linux distributions.
Affected environments observed in field deployments:
| Component | Observed Version |
|---|---|
| CPU 1214C DC/DC/DC | 6ES7 214-1AG40-0XB0, FW 4.5 |
| CPU 1511T-1 PN | 6ES7 511-1TK01-0AB0, FW 2.8.2 |
| TIA Portal (project side) | V13 SP1, V15.1, V16, V17, V18, V20 |
| Web server | Enabled, HTTPS optional, user-level file access |
Root Cause: Referrer-Based CSRF Protection
Siemens enhanced the embedded web server on S7-1200/S7-1500 CPUs to mitigate cross-site request forgery on the FileBrowser endpoint. The check is not a true CSRF token; it is a Referer header inspection. The web server requires the incoming GET /FileBrowser/Download to carry a Referer header whose value points to a path inside the web server, typically /Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs.
The browser naturally sets this header when the user clicks a download link on the FileBrowser overview page. Command-line tools such as curl, wget, PowerShell's Invoke-WebRequest, or any custom HTTP client omit the header by default, which is why the request is rejected. From the perspective of the CPU, the request looks like a forged cross-site request that originated outside the embedded server.
Referer header that points to the FileBrowser page of the same host.Two distinct failure modes appear, depending on firmware:
- HTTP 200 with HTML body – the script receives a 200 OK but the file is empty or contains the web server login page HTML. This occurs when the user is not yet authenticated or when the request hits the login page handler.
- HTTP 403 / "File operation not permitted - no referrer" – the script receives an error page. This is the documented behavior on FW 4.2 and later where the FileBrowser action validates the Referer before serving the file.
Prerequisites
Before applying any of the solutions below, validate the following on the S7-1200 project:
- Web server enabled on the CPU (Device configuration > Web server > Activate web server on this module).
- User administration enabled (Device configuration > Web server > Permit access via HTTPS optional) and at least one user with the right "Read files" and "Write/Delete files" configured under User administration > Access levels.
-
Data logs created in the user program using
DataLogCreate,DataLogOpen,DataLogWrite,DataLogClosefrom the Recipes and data logging instruction set. The CSV files must physically exist under/DataLogs/on the S7-1200's internal flash or on the plugged SIMATIC memory card. See the Siemens TIA Portal V20 Data Logging Overview for the full instruction set and operand requirements. - Network reachability from the host to the PLC IP (ping test, port 80 for HTTP or 443 for HTTPS open).
- Time/date on the CPU set correctly; data log filenames contain the date stamp, and the FileBrowser page enumerates them by name.
Solution 1: curl with Referer Header and Cookie Persistence
The curl utility (available for Windows from curl.se and bundled in most Linux distributions) is the most portable solution. The procedure uses a two-step session: first authenticate and persist the session cookie, then issue the download with a Referer that points to the FileBrowser overview page.
Step 1 – Authenticate and save cookie:
curl -c cookie.txt \
-d "<USER>=<PASSWORD>" \
"http://192.168.1.151/FormLogin"
The -c flag writes the session cookie (typically siemens_ad_secure_session for HTTPS or a non-secure equivalent for HTTP) to cookie.txt. Replace <USER> with a user that has been granted the "Read files" right; this is mandatory when user administration is enabled, otherwise the FileBrowser returns a login page regardless of the Referer.
Step 2 – Download the data log with Referer and cookie:
curl --referer "http://192.168.1.151/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs" \
-b cookie.txt \
-O "http://192.168.1.151/FileBrowser/Download?Path=/DataLogs/MyDataLog.csv"
The --referer (or -e) flag is the critical part. The value must be the FileBrowser overview URL exactly as the embedded web server expects it. The -b cookie.txt flag replays the session cookie obtained in step 1. The -O flag saves the file using its server-side filename.
Batch download of a range of files (bash syntax, also works in Windows curl):
curl --referer "http://192.168.1.151/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs" \
-b cookie.txt \
-O "http://192.168.1.151/FileBrowser/Download?Path=/DataLogs/Doc[1-100].csv"
This fetches Doc1.csv through Doc100.csv in one call. The server will respond with HTTP 404 for any non-existent index, but the existing files are downloaded correctly.
Delete a range of files (optional, requires write access):
curl --referer "http://192.168.1.151/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs" \
-b cookie.txt \
-X DELETE "http://192.168.1.151/FileBrowser/Delete?Path=/DataLogs/Doc[1-100].csv"
DELETE verb must be sent against the /FileBrowser/Delete action, not Download. Without the Referer, the CPU rejects the deletion with the same 403 error.Solution 2: wget with Login and Referer
The GNU wget utility is a viable alternative for users who prefer a single command line. The Windows port is available from the GnuWin32 wget package and from the GNU wget project.
Combined login + download in one command:
wget --save-cookies cookies.txt --keep-session-cookies \
--post-data "<USER>=<PASSWORD>" \
"http://192.168.1.151/FormLogin" -O login.html
wget --load-cookies cookies.txt \
--header "Referer: http://192.168.1.151/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs" \
-O MyDataLog.csv \
"http://192.168.1.151/FileBrowser/Download?Path=/DataLogs/MyDataLog.csv"
The --header "Referer: ..." argument is the wget equivalent of curl's --referer. The Referer URL is identical to the curl example.
To schedule the script, wrap the two commands in a .bat file and trigger it from Windows Task Scheduler or a cron job on Linux. The batch file is invoked with the IP, log name, HTTP/HTTPS scheme, and login state parameterized so the same script can target multiple CPUs.
Solution 3: Python Script with requests and curl Backend
Engineers who need to download multiple logs concurrently, retry on failure, or post-process CSV columns benefit from a Python solution. The script below wraps curl via the subprocess module so that the Referer handling remains identical to solution 1, but the orchestration is Python.
import subprocess
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
PLC_IP = "192.168.1.151"
USER = "your_user"
PASSWORD = "your_password"
LOGS = ["Doc1.csv", "Doc2.csv", "Doc3.csv", "Doc4.csv"]
COOKIE = "cookie.txt"
REFERER = f"http://{PLC_IP}/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs"
def login():
subprocess.run([
"curl", "-c", COOKIE,
"-d", f"{USER}={PASSWORD}",
f"http://{PLC_IP}/FormLogin"
], check=True)
def download(log_name):
url = f"http://{PLC_IP}/FileBrowser/Download?Path=/DataLogs/{log_name}"
out = log_name
if os.path.exists(out):
os.remove(out)
result = subprocess.run([
"curl", "--referer", REFERER,
"-b", COOKIE,
"-o", out,
url
], capture_output=True, text=True)
if result.returncode != 0 or os.path.getsize(out) == 0:
return (log_name, False)
return (log_name, True)
if __name__ == "__main__":
login()
results = {}
with ThreadPoolExecutor(max_workers=4) as ex:
futures = [ex.submit(download, name) for name in LOGS]
for f in as_completed(futures):
name, ok = f.result()
results[name] = ok
for name, ok in results.items():
print(f"{'OK ' if ok else 'FAIL'} {name}")
The script first performs the login against /FormLogin, then fans out downloads in parallel. The empty-file guard protects against the failure mode where the Referer is missing and the server returns a 200 OK with the login page HTML body — those files have non-zero size but contain no CSV rows.
For HTTPS deployments, modify the FormLogin URL to https://.../FormLogin and the cookie name will switch from the HTTP cookie to siemens_ad_secure_session. The rest of the call flow is identical.
Solution 4: PowerShell Invoke-WebRequest
PowerShell can be used, but it has two important constraints: the built-in Invoke-WebRequest cmdlet does not allow easy manipulation of the Referer header on older Windows versions, and on Windows the Referer cannot be spoofed to a different host for security reasons. PowerShell will refuse to send a Referer that does not match the target host, which is normally fine because the FileBrowser URL points to the same host as the download URL.
$plc = "172.16.3.1"
$user = "your_user"
$pass = "your_password"
$log = "LogFiles_A_2021_7_12.csv"
$base = "http://$plc"
$ref = "$base/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs"
$dst = Join-Path $PSScriptRoot $log
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$login = Invoke-WebRequest -Uri "$base/FormLogin" `
-Method POST `
-Body "$user=$pass" `
-WebSession $session
Invoke-WebRequest -Uri "$base/FileBrowser/Download?Path=/DataLogs/$log" `
-OutFile $dst `
-WebSession $session `
-Headers @{ Referer = $ref }
if ((Get-Item $dst).Length -lt 100) {
Write-Warning "$log is suspiciously small, check for login HTML payload."
}
http://172.16.3.1/DataLogs/LogFiles_A_2021_7_12.csv — i.e. bypassing the FileBrowser action and hitting the static path — is tempting but returns the HTML of the FileBrowser page rather than the CSV body on firmware 2.8.x and 4.x. Always use the /FileBrowser/Download?Path=... action endpoint with the Referer header.Authentication Deep Dive: Cookie Mechanics
The S7-1200 web server issues a session cookie after a successful FormLogin POST. The cookie name depends on the transport:
| Transport | Cookie Name | Notes |
|---|---|---|
| HTTP |
S7SESSIONID or SID (FW dependent) |
Plaintext, no secure flag, no HttpOnly in older firmware |
| HTTPS | siemens_ad_secure_session |
Secure + HttpOnly, scoped to /
|
The cookie lifetime is the web server's session timeout, configurable in the CPU properties (default 15 minutes). Long-running batch jobs should re-authenticate periodically; otherwise the FileBrowser will return the login page as the file body, which is the most common cause of "empty CSV" reports in the field.
When user administration is disabled in the CPU properties, the FormLogin endpoint still exists but the cookie is issued without credential validation. The Referer check still applies. To remove the need for authentication, set the "Allow everyone to read files" and "Allow everyone to write/delete files" options under Device configuration > Web server > User administration. This is the simplest path for isolated lab networks but is not recommended for production systems.
HTTPS Configuration
When the web server is configured for HTTPS only (Device configuration > Web server > Permit access only via HTTPS), the following changes apply:
- Replace
http://withhttps://in the FormLogin URL, the Referer header, and the Download URL. - Port 443 is implicit; do not add
:443unless the CPU was reconfigured to a non-standard port. - The cookie is now
siemens_ad_secure_session; somewgetbuilds with a strict cookie policy may reject it. Add--no-check-certificatefor self-signed PLC certificates (common in production) or supply the CA bundle with--ca-certificate. - For
curl, add-kto disable certificate validation when the PLC uses a self-signed certificate. This is acceptable on isolated networks; in production, install the CPU certificate into the host's trust store.
The Referer check is identical for HTTP and HTTPS deployments; the firmware does not differentiate based on transport.
Firmware-Specific Behavior
| CPU / Firmware | Referer check | Known quirks |
|---|---|---|
| S7-1200 FW 4.0 – 4.1 | No | Plain GET /FileBrowser/Download?Path=... works without Referer |
| S7-1200 FW 4.2 – 4.6 | Yes | Empty file (size 0) is the typical failure signature when Referer is missing |
| S7-1500 FW 2.6 – 2.8 | Yes | Returns the FileBrowser HTML body inside the file when Referer is missing |
| S7-1500 FW 2.9+ | Yes (tightened) | 403 "no referrer" is returned consistently |
Project upgrades that change the CPU firmware version can silently break a previously working batch download. After every firmware update, re-test the download script. The new firmware will be served by the TIA Portal project only after a full download to the device, and the web server restart that accompanies a STOP-to-RUN transition is when the new Referer policy becomes active.
SD Card Alternative: Local Persistent Storage
For applications that need a continuous data archive without depending on a PC pull, a SIMATIC memory card (e.g., 6ES7 954-8LF02-0AA0, 4 MB, or 6ES7 954-8LT02-0AA0, 12 MB) inserted into the S7-1200 lets the PLC write data logs directly to removable storage. The user program can open a data log with DataLogCreate specifying the storage path, and the files persist across power cycles.
The advantage is that the data archive survives a CPU restart and can be physically transported to a historian PC. The disadvantage is that data log file sizes are bounded by the card capacity and write endurance. For a 1214C with a 4 MB card, expect on the order of 50,000 lines of timestamped data before the card fills. Always size the card to hold at least 30 days of data at the configured sample rate, and add a maintenance task in the user program that deletes data logs older than a configurable retention window using the DataLogDelete instruction.
/DataLogs/ on the card. The same FileBrowser / curl workflow applies when retrieving them; the Referer check is enforced regardless of whether the log lives on internal flash or on the card.Verification and Smoke Test
After applying any of the solutions, run a controlled end-to-end verification:
-
CSV sanity check: open the downloaded file in a text editor. The first line must be the column header generated by the CPU (e.g.,
"Timestamp";"Tag_1";"Tag_2"). If the file starts with<!DOCTYPEor contains<html>, the Referer was not honored — re-check the exact URL string, including the case-sensitivePortal.mwslpath and the%2Fencoding of the slash in thePath=parameter. -
Size check: the file size must scale with the number of
DataLogWritecalls issued. A file that is 0 bytes, 1 byte, or exactly the size of the HTML login page indicates a failed session. - Cookie expiry test: wait for the session timeout, then run the download without re-authenticating. The file should again be the HTML login page, confirming that the session cookie is the next thing to harden.
- Concurrent download test: launch two downloads in parallel. Both files should download successfully. The web server on S7-1200 is single-threaded and will serialize the requests, but neither should fail with a Referer error.
- Power cycle test: power off the CPU, power it back on, and run the script again. The web server takes 20–40 seconds to come up after a STOP-RUN transition; any script that runs too early will receive a connection refused error rather than a Referer error.
Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
| "File operation not permitted - no referrer" | Referer header missing or wrong host | Set --referer to the exact FileBrowser URL of the same host |
| Empty file (0 bytes) | Session expired; no cookie sent | Re-run FormLogin and reuse the cookie |
| File contains HTML | Cookie valid but Referer missing on a 4.2+ firmware | Add the --referer argument |
| HTTP 404 on every log | Wrong path or filenames do not exist | Browse to /DataLogs/ on the web server and copy the exact filename |
| Connection refused | Web server not yet started after CPU restart | Wait 30 s after STOP-RUN; verify with curl /Portal/Portal.mwsl
|
| SSL handshake error | Self-signed certificate not trusted | Add -k to curl or install the cert in the host trust store |
| PowerShell: "Referer header is restricted" | PSVer 5.1+ enforces same-origin Referer | Use curl or wrap curl.exe from within PowerShell |
| Logs disappear after download | DELETE action was sent by mistake | Use GET against /FileBrowser/Download, not /FileBrowser/Delete |
Long-Term Recommendations
For production historian integrations, prefer a TCP/IP-based read of process tags via the S7 communication protocol using libraries such as libnodave, Snap7, or a commercial OPC UA server. The web server FileBrowser approach is convenient for ad-hoc retrieval and lab use, but its single-threaded request handling and the Referer-based protection make it fragile for high-frequency polling.
If the use case demands the web server (e.g., to avoid installing additional software on plant-floor PCs), wrap the validated curl command in a wrapper that re-authenticates on cookie expiry, validates the file size and first-line header, and surfaces failures to a syslog endpoint. This makes the integration recoverable in the face of CPU restarts, network blips, and firmware updates.
FAQ
What is the exact Referer URL for the S7-1200 FileBrowser?
Use http://<PLC-IP>/Portal/Portal.mwsl?PriNav=FileBrowser&Path=%2FDataLogs for HTTP, or the https:// equivalent. The %2F is the URL-encoded forward slash for the DataLogs path. Mismatched casing on Portal.mwsl or the parameter names will cause the Referer check to fail.
Why is my downloaded CSV file empty even though the download returns 200 OK?
The web server is returning the HTML of the login page instead of the CSV body. This happens when the session cookie has expired (default 15 min) or when no user with read rights is configured. Re-authenticate against /FormLogin and ensure the user has the "Read files" access level.
Can the Referer check be disabled on the S7-1200?
No. Siemens does not expose a configuration option to disable the Referer check on the FileBrowser. The only way to satisfy the check is to send a Referer header that points to the FileBrowser overview page of the same host. There is no firmware version on the S7-1200 that removes the check entirely once it has been introduced.
Does the same Referer issue affect S7-1500 CPUs?
Yes. S7-1500 firmware 2.6 and later enforce the same Referer check on the FileBrowser Download action. The 1511T-1 PN on FW 2.8.2 has been confirmed to return the FileBrowser HTML body when the Referer is missing, and FW 2.9+ returns HTTP 403 with the same "no referrer" error as the S7-1200.
Is there a way to bypass the web server entirely and read data logs over TCP/IP?
Data log files live on the CPU's internal flash or on the SD card and are not directly accessible over the S7 communication protocol. To avoid the web server, refactor the application to write process values to a DB block and read them via PUT/GET, S7 communication, or OPC UA. The web server's data log feature is intended for human-readable CSV archives, not for high-frequency machine-to-machine transfers.
Can I use Windows Task Scheduler to run the curl download every minute?
Yes. Save the curl command in a .bat file and create a Task Scheduler task that runs it on a 1-minute repeat. Add a re-authentication step (delete cookie.txt before each run) if the session timeout is shorter than the repeat interval, otherwise the downloads will start failing silently after the first 15 minutes.