Low level Interface to Taxsim with a SAS example

TAXSIM is a network service available via ssh, ftp or http. Notice that it is usually offered as a service, and not a program that is provided. You upload the data, and download the results. This is also the underlying interface used by the taxsim35 on the web, or from Stata. A scriptable client is found on all Windows, OSX and Unix/Linux systems and in SAS, Python, R and many other languages.

Protocol choice

Remote access to taxsim35 is available via ftp, http, email and ssh. The choice depends on what your application software supports and what your firewall allows. Most modern applications will support curl or allow shelling out to ssh and most firewalls will allow ssh.

Taxsim35 low-level basics

Taxsim35 reads a csv file from standard input with variables as described at the Taxsim web page. Only 3 variables (taxsimid, mstat and year) are required - the rest default to zero. Here is a sample file "txpydata.raw" for testing The correct fiitax returned to standard output is 16,700.04:

taxsimid,mstat,year,ltcg 1,2,1970,100000 Of course, you can have as many data lines as you like, up to multiple millions. Taxsim35 will terminate at the first error, and put an error message to standard output - which would be the last few lines of the csv file. Common errors would be non-decimal characters including missing value codes or value labels or non-zero spousal income on a non-joint return. The error message will render the csv file unusable as a csv file but readable with any text editor.


Anyone can log onto taxsimftp.nber.org with the username 'taxsim' and password '02138'. Then upload the csv file to directory /tmp under any arbitrary name. Once the file is completely uploaded, you can download the calculated results by tacking '.txm35' onto the name used in the upload. The calculation actually occurs during the download on our server. Old input files are deleted once a day on ftp, they are never saved with the other protocols. ftp is available on all Linux, OSX and Windows systems, but many firewalls block the Windows implementation. GUI file transfer programs won't work, since the results file won't exist until it is requested.

Example with ftp using curl:

curl -u taxsim:02138 -T txpydata.raw ftp://taxsimftp.nber.org/tmp/userid curl -u taxsim:02138 ftp://taxsimftp.nber.org/tmp/userid.txm35 Curl is in the default install of OSX, Linux and Windows 10 (since autumn of 2019).


If email taxsim@nber.org with an attachment named "txpydata.raw", and that attachment is a plain ASCII .csv file as described above you should get a return email with the a results.raw file of the calculated results as an attachment.

Emailed files are currently limited to 1 megabyte but write to me (feenberg@nber.org) for an exception if you need to process larger files. This is an experimental interface as of March 2021, so if you don't get a response within 5 minutes or so, please contact me.

Error messages should come back in the body of the returned message.


http using curl: http is almost never firewalled but it is possible that a proxy or cache could interfere. One user reports that taxsim35 fails for http submissions if they are much larger than 2,000 records. These problems would be a feature of the client enviroment - there are no limitations imposed at the server..

curl -F txpydata.raw=@txpydata.raw "https://wwwdev.nber.org/uptest/webfile.cgi"


Our taxsim35.nber.org server has the taxsim35 calculator serving as the shell for user taxsimssh (who has no password). Instead of loading a shell to execute arbitrary commands, it loads the tax calculator. Many applications would allow the user to `shell out' to the OS and issue an ssh command with standard input and output redirected to files on the local computer.. ssh -T -o StrictHostKeyChecking=no taxsimssh@taxsimssh.nber.org <txpydata.raw SSH is available in Windows 10 since autumn of 2019. If you run an earlier Windows, try installing openssh or use the ancient ftp client that was supplied with windows since the beginning.

If a firewall blocks the standard ssh port (22) you can specify ports 80 or 443 with the -p option. They respond in exactly the same way.

That's it. Aside from filewalls, you only need to create and upload the file described on the Taxsim web page. Then capture the results file that flows to standard output. But please follow the instructions at http://taxsim.nber.org/taxsim35 carefully. If there are errors in the file, such as non-decimal characters or missing value codes, then the calculation will stop, and the last few lines of the returned file will contain the error message.

Additional Controls

If the default marginal tax rate calculation or level of detail is not to your liking, it is possible to change either with additiona variables. A

These values of mtr affect the marginal tax calculation are:

  • 11 - Wages
  • 70 - Long term capital gains
  • 85 - Primary wage earner
  • 86 - Secondary wage earner

These values of idtl affect the output level:

  • 0 - standard
  • 2 - full
  • 5 - with text description

For example descriptive output with several different marginal tax rates:

taxsimid,mstat,year,ltcg,mtr,idtl 1,2,1970,100000,11,5 1,2,1970,100000,70,5 1,2,1970,100000,85,5 1,2,1970,100000,86,5

A SAS application using ftp

Because SAS has a built-in ftp client, you can "call" taxsim from within a SAS program.

/* Demonstrate SAS Taxsim with a one record dataset. */

data txpydata;
input taxsimid mstat year ltcg;
1 2 1970 100000

filename txpydata ftp "userid" host='taxsimftp.nber.org'
         user='taxsim' pass='02138' cd='tmp';
filename results  ftp "userid.txm35" host='taxsimftp.nber.org'
         user='taxsim' pass='02138' cd='tmp' lrecl=1024;

proc export outfile=txpydata dbms=csv replace;
proc import datafile=results out=results dbms=csv;

proc print; run;

An R application with ftp

The example below uses the RCurl library. Here we create a dataframe, convert it to csv, send it to NBER, retrieve the csv results file, and convert back to a new dataframe. Note that "userid" in the example code could be your userid, to avoid conflicts with other users of taxsim. I would like to thank Christian Jackson for the example. sample_data <- data.frame(taxsimid = 1, mstat = 2, year = 1970, ltcg = 100000, idtl = 2) library(RCurl) write.csv(sample_data, "./txpydata.csv", row.names = F, na="") ftpUpload("./txpydata.csv", "ftp://taxsim:02138@taxsimftp.nber.org/tmp/userid") results <- getURL("ftp://taxsimftp.nber.org/tmp/userid.txm35", userpwd = "taxsim:02138") taxsim_data <- read.csv(text = results) Daniel Feenberg
last update 19 Nov 2021 by drf